blob: cce5a31bf5614fc6de4f2659b98e8e50f1a437c1 [file] [log] [blame]
Charles Chan2e2e3402017-06-19 14:00:53 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Charles Chan2e2e3402017-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 Chan65238242017-06-22 18:03:14 -070019import com.fasterxml.jackson.databind.JsonNode;
20import com.fasterxml.jackson.databind.ObjectMapper;
Charles Chan2e2e3402017-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 Chan48f89a52017-08-18 17:11:34 -070030import org.onosproject.net.config.ConfigApplyDelegate;
Charles Chanba90df12017-11-30 15:37:50 -080031import org.onosproject.net.host.HostLocationProbingService;
Ray Milkeyfacf2862017-08-03 11:58:29 -070032import org.onosproject.net.intf.Interface;
Charles Chan2e2e3402017-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 Chan2e2e3402017-06-19 14:00:53 -070041import org.onosproject.net.flow.TrafficTreatment;
Charles Chan2e2e3402017-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 Chan65238242017-06-22 18:03:14 -070046import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
Charles Chan2e2e3402017-06-19 14:00:53 -070047
48import java.util.Map;
Charles Chan2e2e3402017-06-19 14:00:53 -070049import java.util.Set;
Charles Chan2e2e3402017-06-19 14:00:53 -070050
51import static org.junit.Assert.*;
52
Charles Chan48f89a52017-08-18 17:11:34 -070053/**r
Charles Chan2e2e3402017-06-19 14:00:53 -070054 * Unit test for {@link HostHandler}.
55 */
56public class HostHandlerTest {
Charles Chan2e2e3402017-06-19 14:00:53 -070057 private HostHandler hostHandler;
58
59 // Mocked routing and bridging tables
Charles Chan48f89a52017-08-18 17:11:34 -070060 private static final Map<MockBridgingTableKey, MockBridgingTableValue> BRIDGING_TABLE =
61 Maps.newConcurrentMap();
62 private static final Map<MockRoutingTableKey, MockRoutingTableValue> ROUTING_TABLE =
63 Maps.newConcurrentMap();
Charles Chan23686832017-08-23 14:46:43 -070064 private static final Map<ConnectPoint, Set<IpPrefix>> SUBNET_TABLE = Maps.newConcurrentMap();
Charles Chan2e2e3402017-06-19 14:00:53 -070065 // Mocked Next Id
Charles Chan48f89a52017-08-18 17:11:34 -070066 private static final Map<Integer, TrafficTreatment> NEXT_TABLE = Maps.newConcurrentMap();
Charles Chan2e2e3402017-06-19 14:00:53 -070067
Charles Chanf9a52702017-06-16 15:19:24 -070068 // Host Mac, VLAN
Charles Chan2e2e3402017-06-19 14:00:53 -070069 private static final ProviderId PROVIDER_ID = ProviderId.NONE;
70 private static final MacAddress HOST_MAC = MacAddress.valueOf("00:00:00:00:00:01");
71 private static final VlanId HOST_VLAN_UNTAGGED = VlanId.NONE;
72 private static final HostId HOST_ID_UNTAGGED = HostId.hostId(HOST_MAC, HOST_VLAN_UNTAGGED);
73 private static final VlanId HOST_VLAN_TAGGED = VlanId.vlanId((short) 20);
74 private static final HostId HOST_ID_TAGGED = HostId.hostId(HOST_MAC, HOST_VLAN_TAGGED);
Charles Chanf9a52702017-06-16 15:19:24 -070075 // Host IP
76 private static final IpAddress HOST_IP11 = IpAddress.valueOf("10.0.1.1");
77 private static final IpAddress HOST_IP21 = IpAddress.valueOf("10.0.2.1");
78 private static final IpAddress HOST_IP12 = IpAddress.valueOf("10.0.1.2");
79 private static final IpAddress HOST_IP13 = IpAddress.valueOf("10.0.1.3");
80 private static final IpAddress HOST_IP14 = IpAddress.valueOf("10.0.1.4");
Charles Chan9ff637e2017-09-12 18:57:47 -070081 private static final IpAddress HOST_IP32 = IpAddress.valueOf("10.0.3.2");
Charles Chanf9a52702017-06-16 15:19:24 -070082 // Device
83 private static final DeviceId DEV1 = DeviceId.deviceId("of:0000000000000001");
84 private static final DeviceId DEV2 = DeviceId.deviceId("of:0000000000000002");
Charles Chan9f08b102017-08-09 16:50:15 -070085 private static final DeviceId DEV3 = DeviceId.deviceId("of:0000000000000003");
86 private static final DeviceId DEV4 = DeviceId.deviceId("of:0000000000000004");
87 private static final DeviceId DEV5 = DeviceId.deviceId("of:0000000000000005");
88 private static final DeviceId DEV6 = DeviceId.deviceId("of:0000000000000006");
Charles Chanf9a52702017-06-16 15:19:24 -070089 // Port
90 private static final PortNumber P1 = PortNumber.portNumber(1);
91 private static final PortNumber P2 = PortNumber.portNumber(2);
92 private static final PortNumber P3 = PortNumber.portNumber(3);
Charles Chan65238242017-06-22 18:03:14 -070093 private static final PortNumber P9 = PortNumber.portNumber(9);
Charles Chanf9a52702017-06-16 15:19:24 -070094 // Connect Point
95 private static final ConnectPoint CP11 = new ConnectPoint(DEV1, P1);
96 private static final HostLocation HOST_LOC11 = new HostLocation(CP11, 0);
97 private static final ConnectPoint CP12 = new ConnectPoint(DEV1, P2);
98 private static final HostLocation HOST_LOC12 = new HostLocation(CP12, 0);
99 private static final ConnectPoint CP13 = new ConnectPoint(DEV1, P3);
100 private static final HostLocation HOST_LOC13 = new HostLocation(CP13, 0);
101 private static final ConnectPoint CP21 = new ConnectPoint(DEV2, P1);
102 private static final HostLocation HOST_LOC21 = new HostLocation(CP21, 0);
103 private static final ConnectPoint CP22 = new ConnectPoint(DEV2, P2);
104 private static final HostLocation HOST_LOC22 = new HostLocation(CP22, 0);
Charles Chan65238242017-06-22 18:03:14 -0700105 // Connect Point for dual-homed host failover
106 private static final ConnectPoint CP31 = new ConnectPoint(DEV3, P1);
107 private static final HostLocation HOST_LOC31 = new HostLocation(CP31, 0);
Charles Chan9ff637e2017-09-12 18:57:47 -0700108 private static final ConnectPoint CP32 = new ConnectPoint(DEV3, P2);
109 private static final HostLocation HOST_LOC32 = new HostLocation(CP32, 0);
Charles Chan65238242017-06-22 18:03:14 -0700110 private static final ConnectPoint CP41 = new ConnectPoint(DEV4, P1);
111 private static final HostLocation HOST_LOC41 = new HostLocation(CP41, 0);
112 private static final ConnectPoint CP39 = new ConnectPoint(DEV3, P9);
113 private static final ConnectPoint CP49 = new ConnectPoint(DEV4, P9);
Charles Chan9f08b102017-08-09 16:50:15 -0700114 // Conenct Point for mastership test
115 private static final ConnectPoint CP51 = new ConnectPoint(DEV5, P1);
116 private static final HostLocation HOST_LOC51 = new HostLocation(CP51, 0);
117 private static final ConnectPoint CP61 = new ConnectPoint(DEV6, P1);
118 private static final HostLocation HOST_LOC61 = new HostLocation(CP61, 0);
Charles Chanf9a52702017-06-16 15:19:24 -0700119 // Interface VLAN
Charles Chan2e2e3402017-06-19 14:00:53 -0700120 private static final VlanId INTF_VLAN_UNTAGGED = VlanId.vlanId((short) 10);
Charles Chan2e2e3402017-06-19 14:00:53 -0700121 private static final Set<VlanId> INTF_VLAN_TAGGED = Sets.newHashSet(VlanId.vlanId((short) 20));
122 private static final VlanId INTF_VLAN_NATIVE = VlanId.vlanId((short) 30);
Charles Chan65238242017-06-22 18:03:14 -0700123 private static final Set<VlanId> INTF_VLAN_PAIR = Sets.newHashSet(VlanId.vlanId((short) 10),
124 VlanId.vlanId((short) 20), VlanId.vlanId((short) 30));
Charles Chan9ff637e2017-09-12 18:57:47 -0700125 private static final VlanId INTF_VLAN_OTHER = VlanId.vlanId((short) 40);
Charles Chanf9a52702017-06-16 15:19:24 -0700126 // Interface subnet
127 private static final IpPrefix INTF_PREFIX1 = IpPrefix.valueOf("10.0.1.254/24");
128 private static final IpPrefix INTF_PREFIX2 = IpPrefix.valueOf("10.0.2.254/24");
Charles Chan9ff637e2017-09-12 18:57:47 -0700129 private static final IpPrefix INTF_PREFIX3 = IpPrefix.valueOf("10.0.3.254/24");
Charles Chanf9a52702017-06-16 15:19:24 -0700130 private static final InterfaceIpAddress INTF_IP1 =
131 new InterfaceIpAddress(INTF_PREFIX1.address(), INTF_PREFIX1);
132 private static final InterfaceIpAddress INTF_IP2 =
133 new InterfaceIpAddress(INTF_PREFIX2.address(), INTF_PREFIX2);
Charles Chan9ff637e2017-09-12 18:57:47 -0700134 private static final InterfaceIpAddress INTF_IP3 =
135 new InterfaceIpAddress(INTF_PREFIX3.address(), INTF_PREFIX3);
Charles Chan48f89a52017-08-18 17:11:34 -0700136 // Interfaces
137 private static final Interface INTF11 =
138 new Interface(null, CP11, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
139 INTF_VLAN_UNTAGGED, null, null);
140 private static final Interface INTF12 =
141 new Interface(null, CP12, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
142 INTF_VLAN_UNTAGGED, null, null);
143 private static final Interface INTF13 =
144 new Interface(null, CP13, Lists.newArrayList(INTF_IP2), MacAddress.NONE, null,
145 null, INTF_VLAN_TAGGED, INTF_VLAN_NATIVE);
146 private static final Interface INTF21 =
147 new Interface(null, CP21, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
148 INTF_VLAN_UNTAGGED, null, null);
149 private static final Interface INTF22 =
150 new Interface(null, CP22, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
151 INTF_VLAN_UNTAGGED, null, null);
152 private static final Interface INTF31 =
153 new Interface(null, CP31, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
154 INTF_VLAN_UNTAGGED, null, null);
Charles Chan9ff637e2017-09-12 18:57:47 -0700155 private static final Interface INTF32 =
156 new Interface(null, CP32, Lists.newArrayList(INTF_IP3), MacAddress.NONE, null,
157 INTF_VLAN_OTHER, null, null);
Charles Chan48f89a52017-08-18 17:11:34 -0700158 private static final Interface INTF39 =
159 new Interface(null, CP39, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
160 null, INTF_VLAN_PAIR, null);
161 private static final Interface INTF41 =
162 new Interface(null, CP41, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
163 INTF_VLAN_UNTAGGED, null, null);
164 private static final Interface INTF49 =
165 new Interface(null, CP49, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
166 null, INTF_VLAN_PAIR, null);
Charles Chanf9a52702017-06-16 15:19:24 -0700167 // Host
168 private static final Host HOST1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC,
169 HOST_VLAN_UNTAGGED, Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11),
170 false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700171
Charles Chan48f89a52017-08-18 17:11:34 -0700172 // A set of hosts
173 private static final Set<Host> HOSTS = Sets.newHashSet(HOST1);
174 // A set of devices of which we have mastership
175 private static final Set<DeviceId> LOCAL_DEVICES = Sets.newHashSet(DEV1, DEV2, DEV3, DEV4);
176 // A set of interfaces
177 private static final Set<Interface> INTERFACES = Sets.newHashSet(INTF11, INTF12, INTF13, INTF21,
Charles Chan9ff637e2017-09-12 18:57:47 -0700178 INTF22, INTF31, INTF32, INTF39, INTF41, INTF49);
Charles Chan48f89a52017-08-18 17:11:34 -0700179
Charles Chanba90df12017-11-30 15:37:50 -0800180 private MockLocationProbingService mockLocationProbingService;
181
Charles Chan2e2e3402017-06-19 14:00:53 -0700182 @Before
183 public void setUp() throws Exception {
Charles Chan48f89a52017-08-18 17:11:34 -0700184 // Initialize pairDevice and pairLocalPort config
185 ObjectMapper mapper = new ObjectMapper();
186 ConfigApplyDelegate delegate = config -> { };
187
188 SegmentRoutingDeviceConfig dev3Config = new SegmentRoutingDeviceConfig();
189 JsonNode dev3Tree = mapper.createObjectNode();
190 dev3Config.init(DEV3, "host-handler-test", dev3Tree, mapper, delegate);
191 dev3Config.setPairDeviceId(DEV4).setPairLocalPort(P9);
192
193 SegmentRoutingDeviceConfig dev4Config = new SegmentRoutingDeviceConfig();
194 JsonNode dev4Tree = mapper.createObjectNode();
195 dev4Config.init(DEV4, "host-handler-test", dev4Tree, mapper, delegate);
196 dev4Config.setPairDeviceId(DEV3).setPairLocalPort(P9);
197
198 MockNetworkConfigRegistry mockNetworkConfigRegistry = new MockNetworkConfigRegistry();
199 mockNetworkConfigRegistry.applyConfig(dev3Config);
200 mockNetworkConfigRegistry.applyConfig(dev4Config);
201
202 // Initialize Segment Routing Manager
203 SegmentRoutingManager srManager = new MockSegmentRoutingManager(NEXT_TABLE);
Charles Chan2e2e3402017-06-19 14:00:53 -0700204 srManager.cfgService = new NetworkConfigRegistryAdapter();
205 srManager.deviceConfiguration = new DeviceConfiguration(srManager);
Charles Chan48f89a52017-08-18 17:11:34 -0700206 srManager.flowObjectiveService = new MockFlowObjectiveService(BRIDGING_TABLE, NEXT_TABLE);
207 srManager.routingRulePopulator = new MockRoutingRulePopulator(srManager, ROUTING_TABLE);
Charles Chan23686832017-08-23 14:46:43 -0700208 srManager.defaultRoutingHandler = new MockDefaultRoutingHandler(srManager, SUBNET_TABLE);
Charles Chan48f89a52017-08-18 17:11:34 -0700209 srManager.interfaceService = new MockInterfaceService(INTERFACES);
210 srManager.mastershipService = new MockMastershipService(LOCAL_DEVICES);
211 srManager.hostService = new MockHostService(HOSTS);
212 srManager.cfgService = mockNetworkConfigRegistry;
Charles Chanba90df12017-11-30 15:37:50 -0800213 mockLocationProbingService = new MockLocationProbingService();
214 srManager.probingService = mockLocationProbingService;
Charles Chan2e2e3402017-06-19 14:00:53 -0700215
216 hostHandler = new HostHandler(srManager);
217
Charles Chan48f89a52017-08-18 17:11:34 -0700218 ROUTING_TABLE.clear();
219 BRIDGING_TABLE.clear();
Charles Chan2e2e3402017-06-19 14:00:53 -0700220 }
221
222 @Test
223 public void init() throws Exception {
Charles Chanf9a52702017-06-16 15:19:24 -0700224 hostHandler.init(DEV1);
Charles Chan48f89a52017-08-18 17:11:34 -0700225 assertEquals(1, ROUTING_TABLE.size());
226 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
227 assertEquals(1, BRIDGING_TABLE.size());
228 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700229
230 hostHandler.init(DEV2);
Charles Chan48f89a52017-08-18 17:11:34 -0700231 assertEquals(2, ROUTING_TABLE.size());
232 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
233 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
234 assertEquals(2, BRIDGING_TABLE.size());
235 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
236 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700237 }
238
239 @Test(expected = IllegalArgumentException.class)
240 public void testHostAddedAtWrongLocation() throws Exception {
241 hostHandler.processHostAddedAtLocation(HOST1, HOST_LOC13);
242 }
243
244
245 @Test()
246 public void testHostAddedAtCorrectLocation() throws Exception {
247 hostHandler.processHostAddedAtLocation(HOST1, HOST_LOC11);
Charles Chan48f89a52017-08-18 17:11:34 -0700248 assertEquals(1, ROUTING_TABLE.size());
249 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
250 assertEquals(1, BRIDGING_TABLE.size());
251 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700252 }
253
254 @Test
255 public void testHostAdded() throws Exception {
256 Host subject;
257
258 // Untagged host discovered on untagged port
259 // Expect: add one routing rule and one bridging rule
260 subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700261 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700262 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan48f89a52017-08-18 17:11:34 -0700263 assertEquals(1, ROUTING_TABLE.size());
264 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
265 assertEquals(1, BRIDGING_TABLE.size());
266 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700267
268 // Untagged host discovered on tagged/native 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 Chanf9a52702017-06-16 15:19:24 -0700271 Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP21), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700272 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan48f89a52017-08-18 17:11:34 -0700273 assertEquals(2, ROUTING_TABLE.size());
274 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
275 assertEquals(2, BRIDGING_TABLE.size());
276 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_NATIVE)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700277
278 // Tagged host discovered on untagged port
279 // Expect: ignore the host. No rule is added.
280 subject = new DefaultHost(PROVIDER_ID, HOST_ID_TAGGED, HOST_MAC, HOST_VLAN_TAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700281 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700282 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan48f89a52017-08-18 17:11:34 -0700283 assertEquals(2, ROUTING_TABLE.size());
284 assertEquals(2, BRIDGING_TABLE.size());
Charles Chan2e2e3402017-06-19 14:00:53 -0700285
286 // Tagged host discovered on tagged port with the same IP
287 // Expect: update existing route, add one bridging rule
288 subject = new DefaultHost(PROVIDER_ID, HOST_ID_TAGGED, HOST_MAC, HOST_VLAN_TAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700289 Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP21), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700290 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan48f89a52017-08-18 17:11:34 -0700291 assertEquals(2, ROUTING_TABLE.size());
292 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
293 assertEquals(HOST_VLAN_TAGGED, ROUTING_TABLE.get(new MockRoutingTableKey(HOST_LOC13.deviceId(),
Charles Chanf9a52702017-06-16 15:19:24 -0700294 HOST_IP21.toIpPrefix())).vlanId);
Charles Chan48f89a52017-08-18 17:11:34 -0700295 assertEquals(3, BRIDGING_TABLE.size());
296 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, HOST_VLAN_TAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700297 }
298
299 @Test
300 public void testDualHomedHostAdded() throws Exception {
301 // Add a dual-homed host that has 2 locations
302 // Expect: add two routing rules and two bridging rules
303 Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
304 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
305 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan48f89a52017-08-18 17:11:34 -0700306 assertEquals(2, ROUTING_TABLE.size());
307 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
308 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
309 assertEquals(2, BRIDGING_TABLE.size());
310 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
311 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700312 }
313
314 @Test
Charles Chan9ff637e2017-09-12 18:57:47 -0700315 public void testSingleHomedHostAddedOnPairLeaf() throws Exception {
316 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
317 Sets.newHashSet(HOST_LOC32), Sets.newHashSet(HOST_IP32), false);
318
319 // Add a single-homed host with one location
320 // Expect: the pair link should not be utilized
321 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
322 assertEquals(1, ROUTING_TABLE.size());
323 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP32.toIpPrefix())).portNumber);
324 assertEquals(1, BRIDGING_TABLE.size());
325 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_OTHER)).portNumber);
326 }
327
328 @Test
329 public void testDualHomedHostAddedOneByOne() throws Exception {
330 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
331 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11), false);
332 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
333 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
334
335 // Add a dual-homed host with one location
336 // Expect: the pair link is utilized temporarily before the second location is discovered
337 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
338 assertEquals(2, ROUTING_TABLE.size());
339 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
340 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
341 assertEquals(2, BRIDGING_TABLE.size());
342 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
343 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanba90df12017-11-30 15:37:50 -0800344 // Expect probe to be sent out on pair device
345 assertTrue(mockLocationProbingService.verifyProbe(host1, CP41, HostLocationProbingService.ProbeMode.DISCOVER));
Charles Chan9ff637e2017-09-12 18:57:47 -0700346
347 // Add the second location of dual-homed host
348 // Expect: no longer use the pair link
349 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
350 assertEquals(2, ROUTING_TABLE.size());
351 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
Charles Chanba90df12017-11-30 15:37:50 -0800352 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
Charles Chan9ff637e2017-09-12 18:57:47 -0700353 assertEquals(2, BRIDGING_TABLE.size());
354 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanba90df12017-11-30 15:37:50 -0800355 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
356 // FIXME: Delay event handling a little bit to wait for the previous redirection flows to be completed
357 // The permanent solution would be introducing CompletableFuture and wait for it
358 Thread.sleep(HostHandler.HOST_MOVED_DELAY_MS + 50);
359 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
Charles Chan9ff637e2017-09-12 18:57:47 -0700360 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
361 }
362
363 @Test
Charles Chan2e2e3402017-06-19 14:00:53 -0700364 public void testHostRemoved() throws Exception {
365 Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700366 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700367
368 // Add a host
369 // Expect: add one routing rule and one bridging rule
370 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan48f89a52017-08-18 17:11:34 -0700371 assertEquals(1, ROUTING_TABLE.size());
372 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
373 assertEquals(1, BRIDGING_TABLE.size());
374 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700375
376 // Remove the host
377 // Expect: add the routing rule and the bridging rule
Charles Chanf9a52702017-06-16 15:19:24 -0700378 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, subject));
Charles Chan48f89a52017-08-18 17:11:34 -0700379 assertEquals(0, ROUTING_TABLE.size());
380 assertEquals(0, BRIDGING_TABLE.size());
Charles Chanf9a52702017-06-16 15:19:24 -0700381 }
382
383 @Test
384 public void testDualHomedHostRemoved() throws Exception {
385 // Add a dual-homed host that has 2 locations
386 // Expect: add two routing rules and two bridging rules
387 Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
388 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
389 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan48f89a52017-08-18 17:11:34 -0700390 assertEquals(2, ROUTING_TABLE.size());
391 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
392 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
393 assertEquals(2, BRIDGING_TABLE.size());
394 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
395 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700396
397 // Remove a dual-homed host that has 2 locations
398 // Expect: all routing and bridging rules are removed
399 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, subject));
Charles Chan48f89a52017-08-18 17:11:34 -0700400 assertEquals(0, ROUTING_TABLE.size());
401 assertEquals(0, BRIDGING_TABLE.size());
Charles Chan2e2e3402017-06-19 14:00:53 -0700402 }
403
404 @Test
405 public void testHostMoved() throws Exception {
406 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700407 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700408 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700409 Sets.newHashSet(HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700410 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700411 Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700412
413 // Add a host
Charles Chan65238242017-06-22 18:03:14 -0700414 // Expect: add one new routing rule, one new bridging rule
Charles Chan2e2e3402017-06-19 14:00:53 -0700415 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700416 assertEquals(1, ROUTING_TABLE.size());
417 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
418 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
419 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())));
420 assertEquals(1, BRIDGING_TABLE.size());
421 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
422 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700423
Charles Chanf9a52702017-06-16 15:19:24 -0700424 // Move the host to CP13, which has different subnet setting
Charles Chan2e2e3402017-06-19 14:00:53 -0700425 // Expect: remove routing rule. Change vlan in bridging rule.
Charles Chanf9a52702017-06-16 15:19:24 -0700426 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700427 assertEquals(0, ROUTING_TABLE.size());
428 assertEquals(1, BRIDGING_TABLE.size());
429 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_NATIVE)));
430 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700431
Charles Chanf9a52702017-06-16 15:19:24 -0700432 // Move the host to CP21, which has same subnet setting
Charles Chan2e2e3402017-06-19 14:00:53 -0700433 // Expect: add a new routing rule. Change vlan in bridging rule.
Charles Chanf9a52702017-06-16 15:19:24 -0700434 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host3));
Charles Chan48f89a52017-08-18 17:11:34 -0700435 assertEquals(1, ROUTING_TABLE.size());
436 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
437 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
438 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
439 assertEquals(1, BRIDGING_TABLE.size());
440 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
441 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700442 }
443
444 @Test
445 public void testDualHomedHostMoved() throws Exception {
446 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
447 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
448 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
449 Sets.newHashSet(HOST_LOC12, HOST_LOC22), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
450 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
451 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP13, HOST_IP14), false);
452 Host host4 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
453 Sets.newHashSet(HOST_LOC11, HOST_LOC22), Sets.newHashSet(HOST_IP12, HOST_IP13), false);
454
455 // Add a host with IP11, IP12 and LOC11, LOC21
456 // Expect: 4 routing rules and 2 bridging rules
457 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700458 assertEquals(4, ROUTING_TABLE.size());
459 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
460 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
461 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
462 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
463 assertEquals(2, BRIDGING_TABLE.size());
464 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
465 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanf9a52702017-06-16 15:19:24 -0700466
467 // Move the host to LOC12, LOC22 and keep the IP
468 // Expect: 4 routing rules and 2 bridging rules all at the new location
469 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700470 assertEquals(4, ROUTING_TABLE.size());
471 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
472 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
473 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
474 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
475 assertEquals(2, BRIDGING_TABLE.size());
476 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
477 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanf9a52702017-06-16 15:19:24 -0700478
479 // Move the host to LOC11, LOC21 and change the IP to IP13, IP14 at the same time
480 // Expect: 4 routing rules and 2 bridging rules all at the new location
481 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
Charles Chan48f89a52017-08-18 17:11:34 -0700482 assertEquals(4, ROUTING_TABLE.size());
483 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())).portNumber);
484 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP14.toIpPrefix())).portNumber);
485 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())).portNumber);
486 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP14.toIpPrefix())).portNumber);
487 assertEquals(2, BRIDGING_TABLE.size());
488 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
489 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanf9a52702017-06-16 15:19:24 -0700490
491 // Move the host to LOC11, LOC22 and change the IP to IP12, IP13 at the same time
492 // Expect: 4 routing rules and 2 bridging rules all at the new location
493 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host4, host3));
Charles Chan48f89a52017-08-18 17:11:34 -0700494 assertEquals(4, ROUTING_TABLE.size());
495 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
496 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())).portNumber);
497 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
498 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())).portNumber);
499 assertEquals(2, BRIDGING_TABLE.size());
500 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
501 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan2e2e3402017-06-19 14:00:53 -0700502 }
503
504 @Test
Charles Chan9f08b102017-08-09 16:50:15 -0700505 public void testHostMoveToInvalidLocation() throws Exception {
506 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
507 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
508 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
509 Sets.newHashSet(HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
510
511 // Add a host
512 // Expect: add one new routing rule, one new bridging rule
513 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700514 assertEquals(1, ROUTING_TABLE.size());
515 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
516 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
517 assertEquals(1, BRIDGING_TABLE.size());
518 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
519 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan9f08b102017-08-09 16:50:15 -0700520
521 // Move the host to an invalid location
522 // Expect: Old flow is removed. New flow is not created
523 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700524 assertEquals(0, ROUTING_TABLE.size());
525 assertEquals(0, BRIDGING_TABLE.size());
Charles Chan9f08b102017-08-09 16:50:15 -0700526
527 // Move the host to a valid location
528 // Expect: add one new routing rule, one new bridging rule
529 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
Charles Chan48f89a52017-08-18 17:11:34 -0700530 assertEquals(1, ROUTING_TABLE.size());
531 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
532 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
533 assertEquals(1, BRIDGING_TABLE.size());
534 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
535 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan9f08b102017-08-09 16:50:15 -0700536 }
537
538 @Test
539 public void testDualHomedHostMoveToInvalidLocation() throws Exception {
540 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
541 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
542 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
543 Sets.newHashSet(HOST_LOC11, HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
544 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
545 Sets.newHashSet(HOST_LOC61, HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
546
547 // Add a host
548 // Expect: add two new routing rules, two new bridging rules
549 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700550 assertEquals(2, ROUTING_TABLE.size());
551 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
552 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
553 assertEquals(2, BRIDGING_TABLE.size());
554 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
555 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan9f08b102017-08-09 16:50:15 -0700556
557 // Move first host location to an invalid location
558 // Expect: One routing and one bridging flow
559 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700560 assertEquals(1, ROUTING_TABLE.size());
561 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
562 assertEquals(1, BRIDGING_TABLE.size());
563 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan9f08b102017-08-09 16:50:15 -0700564
565 // Move second host location to an invalid location
566 // Expect: No routing or bridging rule
567 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
Charles Chan48f89a52017-08-18 17:11:34 -0700568 assertEquals(0, ROUTING_TABLE.size());
569 assertEquals(0, BRIDGING_TABLE.size());
Charles Chan9f08b102017-08-09 16:50:15 -0700570
571 // Move second host location back to a valid location
572 // Expect: One routing and one bridging flow
573 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host3));
Charles Chan48f89a52017-08-18 17:11:34 -0700574 assertEquals(1, ROUTING_TABLE.size());
575 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
576 assertEquals(1, BRIDGING_TABLE.size());
577 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan9f08b102017-08-09 16:50:15 -0700578
579 // Move first host location back to a valid location
580 // Expect: Two routing and two bridging flow
581 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
Charles Chan48f89a52017-08-18 17:11:34 -0700582 assertEquals(2, ROUTING_TABLE.size());
583 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
584 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
585 assertEquals(2, BRIDGING_TABLE.size());
586 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
587 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan9f08b102017-08-09 16:50:15 -0700588 }
589
590 @Test
Charles Chan65238242017-06-22 18:03:14 -0700591 public void testDualHomingSingleLocationFail() throws Exception {
592 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
593 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
594 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
595 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
596
597 // Add a host
598 // Expect: add four new routing rules, two new bridging rules
599 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700600 assertEquals(4, ROUTING_TABLE.size());
601 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
602 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
603 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
604 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
605 assertEquals(2, BRIDGING_TABLE.size());
606 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
607 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan65238242017-06-22 18:03:14 -0700608
609 // Host becomes single-homed
610 // Expect: redirect flows from host location to pair link
611 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700612 assertEquals(4, ROUTING_TABLE.size());
613 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
614 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
615 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
616 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
617 assertEquals(2, BRIDGING_TABLE.size());
618 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
619 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan65238242017-06-22 18:03:14 -0700620
621 // Host becomes dual-homed again
622 // Expect: Redirect flows from pair link back to host location
623 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
Charles Chan48f89a52017-08-18 17:11:34 -0700624 assertEquals(4, ROUTING_TABLE.size());
625 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
626 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
Charles Chanba90df12017-11-30 15:37:50 -0800627 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
628 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
Charles Chan48f89a52017-08-18 17:11:34 -0700629 assertEquals(2, BRIDGING_TABLE.size());
630 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanba90df12017-11-30 15:37:50 -0800631 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
632 // FIXME: Delay event handling a little bit to wait for the previous redirection flows to be completed
633 // The permanent solution would be introducing CompletableFuture and wait for it
634 Thread.sleep(HostHandler.HOST_MOVED_DELAY_MS + 50);
635 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
636 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
Charles Chan48f89a52017-08-18 17:11:34 -0700637 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan65238242017-06-22 18:03:14 -0700638 }
639
640 @Test
641 public void testDualHomingBothLocationFail() throws Exception {
642 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
643 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
644 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
645 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
646
647 // Add a host
648 // Expect: add four new routing rules, two new bridging rules
649 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700650 assertEquals(4, ROUTING_TABLE.size());
651 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
652 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
653 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
654 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
655 assertEquals(2, BRIDGING_TABLE.size());
656 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
657 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan65238242017-06-22 18:03:14 -0700658
659 // Host becomes single-homed
660 // Expect: redirect flows from host location to pair link
661 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700662 assertEquals(4, ROUTING_TABLE.size());
663 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
664 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
665 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
666 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
667 assertEquals(2, BRIDGING_TABLE.size());
668 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
669 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan65238242017-06-22 18:03:14 -0700670
671 // Host loses both locations
672 // Expect: Remove last location and all previous redirection flows
673 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, host2));
Charles Chan48f89a52017-08-18 17:11:34 -0700674 assertEquals(0, ROUTING_TABLE.size());
675 assertEquals(0, BRIDGING_TABLE.size());
Charles Chan65238242017-06-22 18:03:14 -0700676 }
677
678 @Test
Charles Chan2e2e3402017-06-19 14:00:53 -0700679 public void testHostUpdated() throws Exception {
680 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700681 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700682 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700683 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP21), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700684 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700685 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP12), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700686
687 // Add a host
Charles Chanf9a52702017-06-16 15:19:24 -0700688 // Expect: add one new routing rule. Add one new bridging rule.
Charles Chan2e2e3402017-06-19 14:00:53 -0700689 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700690 assertEquals(1, ROUTING_TABLE.size());
691 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
692 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
693 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
694 assertEquals(1, BRIDGING_TABLE.size());
695 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(HOST_LOC11.deviceId(), HOST_MAC,
696 INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700697
698 // Update the host IP to same subnet
699 // Expect: update routing rule with new IP. No change to bridging rule.
700 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700701 assertEquals(1, ROUTING_TABLE.size());
702 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
703 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
704 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
705 assertEquals(1, BRIDGING_TABLE.size());
706 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700707
708 // Update the host IP to different subnet
709 // Expect: Remove routing rule. No change to bridging rule.
710 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host3));
Charles Chan48f89a52017-08-18 17:11:34 -0700711 assertEquals(0, ROUTING_TABLE.size());
712 assertEquals(1, BRIDGING_TABLE.size());
713 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700714 }
715
716 @Test
Charles Chan0ad79082017-11-20 08:46:24 -0800717 public void testDelayedIpAndLocation() throws Exception {
718 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
719 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(), false);
720 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
721 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11), false);
722 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
723 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
724
725 // Add a dual-home host with only one location and no IP
726 // Expect: only bridging redirection works
727 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
728 assertEquals(0, ROUTING_TABLE.size());
729 assertEquals(2, BRIDGING_TABLE.size());
730 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
731 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
732
733 // Discover IP
734 // Expect: routing redirection should also work
Charles Chanba90df12017-11-30 15:37:50 -0800735 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host1));
Charles Chan0ad79082017-11-20 08:46:24 -0800736 assertEquals(2, ROUTING_TABLE.size());
737 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
738 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
739 assertEquals(2, BRIDGING_TABLE.size());
740 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
741 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanba90df12017-11-30 15:37:50 -0800742 // Expect probe to be sent out on pair device
743 assertTrue(mockLocationProbingService.verifyProbe(host2, CP41, HostLocationProbingService.ProbeMode.DISCOVER));
Charles Chan0ad79082017-11-20 08:46:24 -0800744
745 // Discover location
746 // Expect: cancel all redirections
Charles Chanba90df12017-11-30 15:37:50 -0800747 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
Charles Chan0ad79082017-11-20 08:46:24 -0800748 assertEquals(2, ROUTING_TABLE.size());
749 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
Charles Chanba90df12017-11-30 15:37:50 -0800750 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
Charles Chan0ad79082017-11-20 08:46:24 -0800751 assertEquals(2, BRIDGING_TABLE.size());
752 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanba90df12017-11-30 15:37:50 -0800753 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
754 // FIXME: Delay event handling a little bit to wait for the previous redirection flows to be completed
755 // The permanent solution would be introducing CompletableFuture and wait for it
756 Thread.sleep(HostHandler.HOST_MOVED_DELAY_MS + 50);
757 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
Charles Chan0ad79082017-11-20 08:46:24 -0800758 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
759 }
760
761 @Test
762 public void testDelayedIpAndLocation2() throws Exception {
763 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
764 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(), false);
765 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
766 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(), false);
767 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
768 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
769
770 // Add a dual-home host with only one location and no IP
771 // Expect: only bridging redirection works
772 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
773 assertEquals(0, ROUTING_TABLE.size());
774 assertEquals(2, BRIDGING_TABLE.size());
775 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
776 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
777
778 // Discover Location
779 // Expect: cancel bridging redirections
780 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
781 assertEquals(0, ROUTING_TABLE.size());
782 assertEquals(2, BRIDGING_TABLE.size());
783 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
784 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
785
786 // Discover IP
787 // Expect: add IP rules to both location
788 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host2));
789 assertEquals(2, ROUTING_TABLE.size());
790 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
791 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
792 assertEquals(2, BRIDGING_TABLE.size());
793 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
794 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
795 }
796
797 @Test
Charles Chanf9a52702017-06-16 15:19:24 -0700798 public void testDualHomedHostUpdated() throws Exception {
799 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
800 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
801 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
802 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP21), false);
803 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
804 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP13, HOST_IP14), false);
805
806 // Add a dual-homed host with two locations and two IPs
807 // Expect: add four new routing rules. Add two new bridging rules
808 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700809 assertEquals(4, ROUTING_TABLE.size());
810 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
811 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
812 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
813 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
814 assertEquals(2, BRIDGING_TABLE.size());
815 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
816 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700817
818 // Update both host IPs
819 // Expect: update routing rules with new IP. No change to bridging rule.
820 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700821 assertEquals(4, ROUTING_TABLE.size());
822 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
823 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
824 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())));
825 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP14.toIpPrefix())));
826 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
827 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
828 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())));
829 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP14.toIpPrefix())));
830 assertEquals(2, BRIDGING_TABLE.size());
831 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
832 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700833
834 // Update one of the host IP to different subnet
835 // Expect: update routing rule with new IP. No change to bridging rule.
836 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host3));
Charles Chan48f89a52017-08-18 17:11:34 -0700837 assertEquals(2, ROUTING_TABLE.size());
838 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
839 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
840 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
841 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
842 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP21.toIpPrefix())));
843 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
844 assertEquals(2, BRIDGING_TABLE.size());
845 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
846 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700847 }
848
849 @Test
850 public void testBridgingFwdObjBuilder() throws Exception {
851 assertNotNull(hostHandler.bridgingFwdObjBuilder(DEV2, HOST_MAC, HOST_VLAN_UNTAGGED, P1, false));
852 assertNull(hostHandler.bridgingFwdObjBuilder(DEV2, HOST_MAC, HOST_VLAN_UNTAGGED, P3, false));
Charles Chan2e2e3402017-06-19 14:00:53 -0700853 }
Ray Milkeyfacf2862017-08-03 11:58:29 -0700854}