blob: e33a36da51d36fb2f62a0e71a88793ea7b33f994 [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;
Saurav Dase9c8971e2018-01-18 12:07:33 -0800215 srManager.linkHandler = new MockLinkHandler(srManager);
Charles Chan2e2e3402017-06-19 14:00:53 -0700216
217 hostHandler = new HostHandler(srManager);
218
Charles Chan48f89a52017-08-18 17:11:34 -0700219 ROUTING_TABLE.clear();
220 BRIDGING_TABLE.clear();
Charles Chan2e2e3402017-06-19 14:00:53 -0700221 }
222
223 @Test
224 public void init() throws Exception {
Charles Chanf9a52702017-06-16 15:19:24 -0700225 hostHandler.init(DEV1);
Charles Chan48f89a52017-08-18 17:11:34 -0700226 assertEquals(1, ROUTING_TABLE.size());
227 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
228 assertEquals(1, BRIDGING_TABLE.size());
229 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700230
231 hostHandler.init(DEV2);
Charles Chan48f89a52017-08-18 17:11:34 -0700232 assertEquals(2, ROUTING_TABLE.size());
233 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
234 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
235 assertEquals(2, BRIDGING_TABLE.size());
236 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
237 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700238 }
239
240 @Test(expected = IllegalArgumentException.class)
241 public void testHostAddedAtWrongLocation() throws Exception {
242 hostHandler.processHostAddedAtLocation(HOST1, HOST_LOC13);
243 }
244
245
246 @Test()
247 public void testHostAddedAtCorrectLocation() throws Exception {
248 hostHandler.processHostAddedAtLocation(HOST1, HOST_LOC11);
Charles Chan48f89a52017-08-18 17:11:34 -0700249 assertEquals(1, ROUTING_TABLE.size());
250 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
251 assertEquals(1, BRIDGING_TABLE.size());
252 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700253 }
254
255 @Test
256 public void testHostAdded() throws Exception {
257 Host subject;
258
259 // Untagged host discovered on untagged port
260 // Expect: add one routing rule and one bridging rule
261 subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700262 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700263 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan48f89a52017-08-18 17:11:34 -0700264 assertEquals(1, ROUTING_TABLE.size());
265 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
266 assertEquals(1, BRIDGING_TABLE.size());
267 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700268
269 // Untagged host discovered on tagged/native port
270 // Expect: add one routing rule and one bridging rule
271 subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700272 Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP21), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700273 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan48f89a52017-08-18 17:11:34 -0700274 assertEquals(2, ROUTING_TABLE.size());
275 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
276 assertEquals(2, BRIDGING_TABLE.size());
277 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_NATIVE)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700278
279 // Tagged host discovered on untagged port
280 // Expect: ignore the host. No rule is added.
281 subject = new DefaultHost(PROVIDER_ID, HOST_ID_TAGGED, HOST_MAC, HOST_VLAN_TAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700282 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700283 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan48f89a52017-08-18 17:11:34 -0700284 assertEquals(2, ROUTING_TABLE.size());
285 assertEquals(2, BRIDGING_TABLE.size());
Charles Chan2e2e3402017-06-19 14:00:53 -0700286
287 // Tagged host discovered on tagged port with the same IP
288 // Expect: update existing route, add one bridging rule
289 subject = new DefaultHost(PROVIDER_ID, HOST_ID_TAGGED, HOST_MAC, HOST_VLAN_TAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700290 Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP21), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700291 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan48f89a52017-08-18 17:11:34 -0700292 assertEquals(2, ROUTING_TABLE.size());
293 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
294 assertEquals(HOST_VLAN_TAGGED, ROUTING_TABLE.get(new MockRoutingTableKey(HOST_LOC13.deviceId(),
Charles Chanf9a52702017-06-16 15:19:24 -0700295 HOST_IP21.toIpPrefix())).vlanId);
Charles Chan48f89a52017-08-18 17:11:34 -0700296 assertEquals(3, BRIDGING_TABLE.size());
297 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, HOST_VLAN_TAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700298 }
299
300 @Test
301 public void testDualHomedHostAdded() throws Exception {
302 // Add a dual-homed host that has 2 locations
303 // Expect: add two routing rules and two bridging rules
304 Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
305 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
306 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan48f89a52017-08-18 17:11:34 -0700307 assertEquals(2, ROUTING_TABLE.size());
308 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
309 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
310 assertEquals(2, BRIDGING_TABLE.size());
311 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
312 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700313 }
314
315 @Test
Charles Chan9ff637e2017-09-12 18:57:47 -0700316 public void testSingleHomedHostAddedOnPairLeaf() throws Exception {
317 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
318 Sets.newHashSet(HOST_LOC32), Sets.newHashSet(HOST_IP32), false);
319
320 // Add a single-homed host with one location
321 // Expect: the pair link should not be utilized
322 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
323 assertEquals(1, ROUTING_TABLE.size());
324 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP32.toIpPrefix())).portNumber);
325 assertEquals(1, BRIDGING_TABLE.size());
326 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_OTHER)).portNumber);
327 }
328
329 @Test
330 public void testDualHomedHostAddedOneByOne() throws Exception {
331 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
332 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11), false);
333 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
334 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
335
336 // Add a dual-homed host with one location
337 // Expect: the pair link is utilized temporarily before the second location is discovered
338 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
339 assertEquals(2, ROUTING_TABLE.size());
340 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
341 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
342 assertEquals(2, BRIDGING_TABLE.size());
343 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
344 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanba90df12017-11-30 15:37:50 -0800345 // Expect probe to be sent out on pair device
346 assertTrue(mockLocationProbingService.verifyProbe(host1, CP41, HostLocationProbingService.ProbeMode.DISCOVER));
Charles Chan9ff637e2017-09-12 18:57:47 -0700347
348 // Add the second location of dual-homed host
349 // Expect: no longer use the pair link
350 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
351 assertEquals(2, ROUTING_TABLE.size());
352 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
Charles Chanba90df12017-11-30 15:37:50 -0800353 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
Charles Chan9ff637e2017-09-12 18:57:47 -0700354 assertEquals(2, BRIDGING_TABLE.size());
355 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanba90df12017-11-30 15:37:50 -0800356 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
357 // FIXME: Delay event handling a little bit to wait for the previous redirection flows to be completed
358 // The permanent solution would be introducing CompletableFuture and wait for it
359 Thread.sleep(HostHandler.HOST_MOVED_DELAY_MS + 50);
360 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
Charles Chan9ff637e2017-09-12 18:57:47 -0700361 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
362 }
363
364 @Test
Charles Chan2e2e3402017-06-19 14:00:53 -0700365 public void testHostRemoved() throws Exception {
366 Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700367 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700368
369 // Add a host
370 // Expect: add one routing rule and one bridging rule
371 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan48f89a52017-08-18 17:11:34 -0700372 assertEquals(1, ROUTING_TABLE.size());
373 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
374 assertEquals(1, BRIDGING_TABLE.size());
375 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700376
377 // Remove the host
378 // Expect: add the routing rule and the bridging rule
Charles Chanf9a52702017-06-16 15:19:24 -0700379 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, subject));
Charles Chan48f89a52017-08-18 17:11:34 -0700380 assertEquals(0, ROUTING_TABLE.size());
381 assertEquals(0, BRIDGING_TABLE.size());
Charles Chanf9a52702017-06-16 15:19:24 -0700382 }
383
384 @Test
385 public void testDualHomedHostRemoved() throws Exception {
386 // Add a dual-homed host that has 2 locations
387 // Expect: add two routing rules and two bridging rules
388 Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
389 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
390 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan48f89a52017-08-18 17:11:34 -0700391 assertEquals(2, ROUTING_TABLE.size());
392 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
393 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
394 assertEquals(2, BRIDGING_TABLE.size());
395 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
396 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700397
398 // Remove a dual-homed host that has 2 locations
399 // Expect: all routing and bridging rules are removed
400 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, subject));
Charles Chan48f89a52017-08-18 17:11:34 -0700401 assertEquals(0, ROUTING_TABLE.size());
402 assertEquals(0, BRIDGING_TABLE.size());
Charles Chan2e2e3402017-06-19 14:00:53 -0700403 }
404
405 @Test
406 public void testHostMoved() throws Exception {
407 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700408 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700409 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700410 Sets.newHashSet(HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700411 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700412 Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700413
414 // Add a host
Charles Chan65238242017-06-22 18:03:14 -0700415 // Expect: add one new routing rule, one new bridging rule
Charles Chan2e2e3402017-06-19 14:00:53 -0700416 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700417 assertEquals(1, ROUTING_TABLE.size());
418 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
419 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
420 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())));
421 assertEquals(1, BRIDGING_TABLE.size());
422 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
423 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700424
Charles Chanf9a52702017-06-16 15:19:24 -0700425 // Move the host to CP13, which has different subnet setting
Charles Chan2e2e3402017-06-19 14:00:53 -0700426 // Expect: remove routing rule. Change vlan in bridging rule.
Charles Chanf9a52702017-06-16 15:19:24 -0700427 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700428 assertEquals(0, ROUTING_TABLE.size());
429 assertEquals(1, BRIDGING_TABLE.size());
430 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_NATIVE)));
431 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700432
Charles Chanf9a52702017-06-16 15:19:24 -0700433 // Move the host to CP21, which has same subnet setting
Charles Chan2e2e3402017-06-19 14:00:53 -0700434 // Expect: add a new routing rule. Change vlan in bridging rule.
Charles Chanf9a52702017-06-16 15:19:24 -0700435 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host3));
Charles Chan48f89a52017-08-18 17:11:34 -0700436 assertEquals(1, ROUTING_TABLE.size());
437 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
438 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
439 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
440 assertEquals(1, BRIDGING_TABLE.size());
441 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
442 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700443 }
444
445 @Test
446 public void testDualHomedHostMoved() throws Exception {
447 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
448 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
449 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
450 Sets.newHashSet(HOST_LOC12, HOST_LOC22), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
451 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
452 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP13, HOST_IP14), false);
453 Host host4 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
454 Sets.newHashSet(HOST_LOC11, HOST_LOC22), Sets.newHashSet(HOST_IP12, HOST_IP13), false);
455
456 // Add a host with IP11, IP12 and LOC11, LOC21
457 // Expect: 4 routing rules and 2 bridging rules
458 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700459 assertEquals(4, ROUTING_TABLE.size());
460 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
461 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
462 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
463 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
464 assertEquals(2, BRIDGING_TABLE.size());
465 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
466 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanf9a52702017-06-16 15:19:24 -0700467
468 // Move the host to LOC12, LOC22 and keep the IP
469 // Expect: 4 routing rules and 2 bridging rules all at the new location
470 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700471 assertEquals(4, ROUTING_TABLE.size());
472 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
473 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
474 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
475 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
476 assertEquals(2, BRIDGING_TABLE.size());
477 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
478 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanf9a52702017-06-16 15:19:24 -0700479
480 // Move the host to LOC11, LOC21 and change the IP to IP13, IP14 at the same time
481 // Expect: 4 routing rules and 2 bridging rules all at the new location
482 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
Charles Chan48f89a52017-08-18 17:11:34 -0700483 assertEquals(4, ROUTING_TABLE.size());
484 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())).portNumber);
485 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP14.toIpPrefix())).portNumber);
486 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())).portNumber);
487 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP14.toIpPrefix())).portNumber);
488 assertEquals(2, BRIDGING_TABLE.size());
489 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
490 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanf9a52702017-06-16 15:19:24 -0700491
492 // Move the host to LOC11, LOC22 and change the IP to IP12, IP13 at the same time
493 // Expect: 4 routing rules and 2 bridging rules all at the new location
494 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host4, host3));
Charles Chan48f89a52017-08-18 17:11:34 -0700495 assertEquals(4, ROUTING_TABLE.size());
496 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
497 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())).portNumber);
498 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
499 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())).portNumber);
500 assertEquals(2, BRIDGING_TABLE.size());
501 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
502 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan2e2e3402017-06-19 14:00:53 -0700503 }
504
505 @Test
Charles Chan9f08b102017-08-09 16:50:15 -0700506 public void testHostMoveToInvalidLocation() throws Exception {
507 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
508 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
509 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
510 Sets.newHashSet(HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
511
512 // Add a host
513 // Expect: add one new routing rule, one new bridging rule
514 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700515 assertEquals(1, ROUTING_TABLE.size());
516 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
517 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
518 assertEquals(1, BRIDGING_TABLE.size());
519 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
520 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan9f08b102017-08-09 16:50:15 -0700521
522 // Move the host to an invalid location
523 // Expect: Old flow is removed. New flow is not created
524 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700525 assertEquals(0, ROUTING_TABLE.size());
526 assertEquals(0, BRIDGING_TABLE.size());
Charles Chan9f08b102017-08-09 16:50:15 -0700527
528 // Move the host to a valid location
529 // Expect: add one new routing rule, one new bridging rule
530 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
Charles Chan48f89a52017-08-18 17:11:34 -0700531 assertEquals(1, ROUTING_TABLE.size());
532 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
533 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
534 assertEquals(1, BRIDGING_TABLE.size());
535 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
536 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan9f08b102017-08-09 16:50:15 -0700537 }
538
539 @Test
540 public void testDualHomedHostMoveToInvalidLocation() throws Exception {
541 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
542 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
543 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
544 Sets.newHashSet(HOST_LOC11, HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
545 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
546 Sets.newHashSet(HOST_LOC61, HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
547
548 // Add a host
549 // Expect: add two new routing rules, two new bridging rules
550 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700551 assertEquals(2, ROUTING_TABLE.size());
552 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
553 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
554 assertEquals(2, BRIDGING_TABLE.size());
555 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
556 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan9f08b102017-08-09 16:50:15 -0700557
558 // Move first host location to an invalid location
559 // Expect: One routing and one bridging flow
560 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700561 assertEquals(1, ROUTING_TABLE.size());
562 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
563 assertEquals(1, BRIDGING_TABLE.size());
564 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan9f08b102017-08-09 16:50:15 -0700565
566 // Move second host location to an invalid location
567 // Expect: No routing or bridging rule
568 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
Charles Chan48f89a52017-08-18 17:11:34 -0700569 assertEquals(0, ROUTING_TABLE.size());
570 assertEquals(0, BRIDGING_TABLE.size());
Charles Chan9f08b102017-08-09 16:50:15 -0700571
572 // Move second host location back to a valid location
573 // Expect: One routing and one bridging flow
574 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host3));
Charles Chan48f89a52017-08-18 17:11:34 -0700575 assertEquals(1, ROUTING_TABLE.size());
576 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
577 assertEquals(1, BRIDGING_TABLE.size());
578 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan9f08b102017-08-09 16:50:15 -0700579
580 // Move first host location back to a valid location
581 // Expect: Two routing and two bridging flow
582 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
Charles Chan48f89a52017-08-18 17:11:34 -0700583 assertEquals(2, ROUTING_TABLE.size());
584 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
585 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
586 assertEquals(2, BRIDGING_TABLE.size());
587 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
588 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan9f08b102017-08-09 16:50:15 -0700589 }
590
591 @Test
Charles Chan65238242017-06-22 18:03:14 -0700592 public void testDualHomingSingleLocationFail() throws Exception {
593 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
594 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
595 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
596 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
597
598 // Add a host
599 // Expect: add four new routing rules, two new bridging rules
600 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700601 assertEquals(4, ROUTING_TABLE.size());
602 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
603 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
604 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
605 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
606 assertEquals(2, BRIDGING_TABLE.size());
607 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
608 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan65238242017-06-22 18:03:14 -0700609
610 // Host becomes single-homed
611 // Expect: redirect flows from host location to pair link
612 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700613 assertEquals(4, ROUTING_TABLE.size());
614 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
615 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
616 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
617 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
618 assertEquals(2, BRIDGING_TABLE.size());
619 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
620 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan65238242017-06-22 18:03:14 -0700621
622 // Host becomes dual-homed again
623 // Expect: Redirect flows from pair link back to host location
624 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
Charles Chan48f89a52017-08-18 17:11:34 -0700625 assertEquals(4, ROUTING_TABLE.size());
626 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
627 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
Charles Chanba90df12017-11-30 15:37:50 -0800628 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
629 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
Charles Chan48f89a52017-08-18 17:11:34 -0700630 assertEquals(2, BRIDGING_TABLE.size());
631 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanba90df12017-11-30 15:37:50 -0800632 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
633 // FIXME: Delay event handling a little bit to wait for the previous redirection flows to be completed
634 // The permanent solution would be introducing CompletableFuture and wait for it
635 Thread.sleep(HostHandler.HOST_MOVED_DELAY_MS + 50);
636 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
637 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
Charles Chan48f89a52017-08-18 17:11:34 -0700638 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan65238242017-06-22 18:03:14 -0700639 }
640
641 @Test
642 public void testDualHomingBothLocationFail() throws Exception {
643 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
644 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
645 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
646 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
647
648 // Add a host
649 // Expect: add four new routing rules, two new bridging rules
650 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700651 assertEquals(4, ROUTING_TABLE.size());
652 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
653 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
654 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
655 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
656 assertEquals(2, BRIDGING_TABLE.size());
657 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
658 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan65238242017-06-22 18:03:14 -0700659
660 // Host becomes single-homed
661 // Expect: redirect flows from host location to pair link
662 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700663 assertEquals(4, ROUTING_TABLE.size());
664 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
665 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
666 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
667 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
668 assertEquals(2, BRIDGING_TABLE.size());
669 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
670 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan65238242017-06-22 18:03:14 -0700671
672 // Host loses both locations
673 // Expect: Remove last location and all previous redirection flows
674 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, host2));
Charles Chan48f89a52017-08-18 17:11:34 -0700675 assertEquals(0, ROUTING_TABLE.size());
676 assertEquals(0, BRIDGING_TABLE.size());
Charles Chan65238242017-06-22 18:03:14 -0700677 }
678
679 @Test
Charles Chan2e2e3402017-06-19 14:00:53 -0700680 public void testHostUpdated() throws Exception {
681 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700682 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700683 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700684 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP21), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700685 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700686 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP12), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700687
688 // Add a host
Charles Chanf9a52702017-06-16 15:19:24 -0700689 // Expect: add one new routing rule. Add one new bridging rule.
Charles Chan2e2e3402017-06-19 14:00:53 -0700690 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700691 assertEquals(1, ROUTING_TABLE.size());
692 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
693 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
694 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
695 assertEquals(1, BRIDGING_TABLE.size());
696 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(HOST_LOC11.deviceId(), HOST_MAC,
697 INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700698
699 // Update the host IP to same subnet
700 // Expect: update routing rule with new IP. No change to bridging rule.
701 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700702 assertEquals(1, ROUTING_TABLE.size());
703 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
704 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
705 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
706 assertEquals(1, BRIDGING_TABLE.size());
707 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700708
709 // Update the host IP to different subnet
710 // Expect: Remove routing rule. No change to bridging rule.
711 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host3));
Charles Chan48f89a52017-08-18 17:11:34 -0700712 assertEquals(0, ROUTING_TABLE.size());
713 assertEquals(1, BRIDGING_TABLE.size());
714 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700715 }
716
717 @Test
Charles Chan0ad79082017-11-20 08:46:24 -0800718 public void testDelayedIpAndLocation() throws Exception {
719 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
720 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(), false);
721 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
722 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11), false);
723 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
724 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
725
726 // Add a dual-home host with only one location and no IP
727 // Expect: only bridging redirection works
728 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
729 assertEquals(0, ROUTING_TABLE.size());
730 assertEquals(2, BRIDGING_TABLE.size());
731 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
732 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
733
734 // Discover IP
735 // Expect: routing redirection should also work
Charles Chanba90df12017-11-30 15:37:50 -0800736 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host1));
Charles Chan0ad79082017-11-20 08:46:24 -0800737 assertEquals(2, ROUTING_TABLE.size());
738 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
739 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
740 assertEquals(2, BRIDGING_TABLE.size());
741 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
742 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanba90df12017-11-30 15:37:50 -0800743 // Expect probe to be sent out on pair device
744 assertTrue(mockLocationProbingService.verifyProbe(host2, CP41, HostLocationProbingService.ProbeMode.DISCOVER));
Charles Chan0ad79082017-11-20 08:46:24 -0800745
746 // Discover location
747 // Expect: cancel all redirections
Charles Chanba90df12017-11-30 15:37:50 -0800748 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
Charles Chan0ad79082017-11-20 08:46:24 -0800749 assertEquals(2, ROUTING_TABLE.size());
750 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
Charles Chanba90df12017-11-30 15:37:50 -0800751 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
Charles Chan0ad79082017-11-20 08:46:24 -0800752 assertEquals(2, BRIDGING_TABLE.size());
753 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanba90df12017-11-30 15:37:50 -0800754 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
755 // FIXME: Delay event handling a little bit to wait for the previous redirection flows to be completed
756 // The permanent solution would be introducing CompletableFuture and wait for it
757 Thread.sleep(HostHandler.HOST_MOVED_DELAY_MS + 50);
758 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
Charles Chan0ad79082017-11-20 08:46:24 -0800759 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
760 }
761
762 @Test
763 public void testDelayedIpAndLocation2() throws Exception {
764 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
765 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(), false);
766 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
767 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(), false);
768 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
769 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
770
771 // Add a dual-home host with only one location and no IP
772 // Expect: only bridging redirection works
773 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
774 assertEquals(0, ROUTING_TABLE.size());
775 assertEquals(2, BRIDGING_TABLE.size());
776 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
777 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
778
779 // Discover Location
780 // Expect: cancel bridging redirections
781 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
782 assertEquals(0, ROUTING_TABLE.size());
783 assertEquals(2, BRIDGING_TABLE.size());
784 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
785 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
786
787 // Discover IP
788 // Expect: add IP rules to both location
789 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host2));
790 assertEquals(2, ROUTING_TABLE.size());
791 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
792 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
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
798 @Test
Charles Chanf9a52702017-06-16 15:19:24 -0700799 public void testDualHomedHostUpdated() throws Exception {
800 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
801 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
802 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
803 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP21), false);
804 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
805 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP13, HOST_IP14), false);
806
807 // Add a dual-homed host with two locations and two IPs
808 // Expect: add four new routing rules. Add two new bridging rules
809 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700810 assertEquals(4, ROUTING_TABLE.size());
811 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
812 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
813 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
814 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
815 assertEquals(2, BRIDGING_TABLE.size());
816 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
817 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700818
819 // Update both host IPs
820 // Expect: update routing rules with new IP. No change to bridging rule.
821 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host1));
Charles Chan48f89a52017-08-18 17:11:34 -0700822 assertEquals(4, ROUTING_TABLE.size());
823 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
824 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
825 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())));
826 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP14.toIpPrefix())));
827 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
828 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
829 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())));
830 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP14.toIpPrefix())));
831 assertEquals(2, BRIDGING_TABLE.size());
832 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
833 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700834
835 // Update one of the host IP to different subnet
836 // Expect: update routing rule with new IP. No change to bridging rule.
837 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host3));
Charles Chan48f89a52017-08-18 17:11:34 -0700838 assertEquals(2, ROUTING_TABLE.size());
839 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
840 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
841 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
842 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
843 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP21.toIpPrefix())));
844 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
845 assertEquals(2, BRIDGING_TABLE.size());
846 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
847 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700848 }
849
850 @Test
851 public void testBridgingFwdObjBuilder() throws Exception {
852 assertNotNull(hostHandler.bridgingFwdObjBuilder(DEV2, HOST_MAC, HOST_VLAN_UNTAGGED, P1, false));
853 assertNull(hostHandler.bridgingFwdObjBuilder(DEV2, HOST_MAC, HOST_VLAN_UNTAGGED, P3, false));
Charles Chan2e2e3402017-06-19 14:00:53 -0700854 }
Ray Milkeyfacf2862017-08-03 11:58:29 -0700855}