blob: 26420ac824d055052d67430ef0798f8f2c8935b8 [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 Chan1a3b02a2017-08-18 17:11:34 -070030import org.onosproject.net.config.ConfigApplyDelegate;
Charles Chan47933752017-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 Chan2ff1bac2018-03-29 16:03:41 -070047import org.onosproject.store.service.StorageService;
48import org.onosproject.store.service.TestConsistentMap;
Charles Chan2e2e3402017-06-19 14:00:53 -070049
50import java.util.Map;
Charles Chan2e2e3402017-06-19 14:00:53 -070051import java.util.Set;
Charles Chan2e2e3402017-06-19 14:00:53 -070052
Charles Chan2ff1bac2018-03-29 16:03:41 -070053import static org.easymock.EasyMock.createMock;
54import static org.easymock.EasyMock.expect;
55import static org.easymock.EasyMock.replay;
Charles Chan2e2e3402017-06-19 14:00:53 -070056import static org.junit.Assert.*;
57
Charles Chan1a3b02a2017-08-18 17:11:34 -070058/**r
Charles Chan2e2e3402017-06-19 14:00:53 -070059 * Unit test for {@link HostHandler}.
60 */
61public class HostHandlerTest {
Charles Chan2e2e3402017-06-19 14:00:53 -070062 private HostHandler hostHandler;
63
64 // Mocked routing and bridging tables
Charles Chan1a3b02a2017-08-18 17:11:34 -070065 private static final Map<MockBridgingTableKey, MockBridgingTableValue> BRIDGING_TABLE =
66 Maps.newConcurrentMap();
67 private static final Map<MockRoutingTableKey, MockRoutingTableValue> ROUTING_TABLE =
68 Maps.newConcurrentMap();
Charles Chan2fde6d42017-08-23 14:46:43 -070069 private static final Map<ConnectPoint, Set<IpPrefix>> SUBNET_TABLE = Maps.newConcurrentMap();
Charles Chan2e2e3402017-06-19 14:00:53 -070070 // Mocked Next Id
Charles Chan1a3b02a2017-08-18 17:11:34 -070071 private static final Map<Integer, TrafficTreatment> NEXT_TABLE = Maps.newConcurrentMap();
Charles Chan2e2e3402017-06-19 14:00:53 -070072
Charles Chanf9a52702017-06-16 15:19:24 -070073 // Host Mac, VLAN
Charles Chan2e2e3402017-06-19 14:00:53 -070074 private static final ProviderId PROVIDER_ID = ProviderId.NONE;
75 private static final MacAddress HOST_MAC = MacAddress.valueOf("00:00:00:00:00:01");
76 private static final VlanId HOST_VLAN_UNTAGGED = VlanId.NONE;
77 private static final HostId HOST_ID_UNTAGGED = HostId.hostId(HOST_MAC, HOST_VLAN_UNTAGGED);
78 private static final VlanId HOST_VLAN_TAGGED = VlanId.vlanId((short) 20);
79 private static final HostId HOST_ID_TAGGED = HostId.hostId(HOST_MAC, HOST_VLAN_TAGGED);
Charles Chanf9a52702017-06-16 15:19:24 -070080 // Host IP
81 private static final IpAddress HOST_IP11 = IpAddress.valueOf("10.0.1.1");
82 private static final IpAddress HOST_IP21 = IpAddress.valueOf("10.0.2.1");
83 private static final IpAddress HOST_IP12 = IpAddress.valueOf("10.0.1.2");
84 private static final IpAddress HOST_IP13 = IpAddress.valueOf("10.0.1.3");
85 private static final IpAddress HOST_IP14 = IpAddress.valueOf("10.0.1.4");
Charles Chan8e786b52017-09-12 18:57:47 -070086 private static final IpAddress HOST_IP32 = IpAddress.valueOf("10.0.3.2");
Charles Chanf9a52702017-06-16 15:19:24 -070087 // Device
88 private static final DeviceId DEV1 = DeviceId.deviceId("of:0000000000000001");
89 private static final DeviceId DEV2 = DeviceId.deviceId("of:0000000000000002");
Charles Chan9f08b102017-08-09 16:50:15 -070090 private static final DeviceId DEV3 = DeviceId.deviceId("of:0000000000000003");
91 private static final DeviceId DEV4 = DeviceId.deviceId("of:0000000000000004");
92 private static final DeviceId DEV5 = DeviceId.deviceId("of:0000000000000005");
93 private static final DeviceId DEV6 = DeviceId.deviceId("of:0000000000000006");
Charles Chanf9a52702017-06-16 15:19:24 -070094 // Port
95 private static final PortNumber P1 = PortNumber.portNumber(1);
96 private static final PortNumber P2 = PortNumber.portNumber(2);
97 private static final PortNumber P3 = PortNumber.portNumber(3);
Charles Chan65238242017-06-22 18:03:14 -070098 private static final PortNumber P9 = PortNumber.portNumber(9);
Charles Chanf9a52702017-06-16 15:19:24 -070099 // Connect Point
100 private static final ConnectPoint CP11 = new ConnectPoint(DEV1, P1);
101 private static final HostLocation HOST_LOC11 = new HostLocation(CP11, 0);
102 private static final ConnectPoint CP12 = new ConnectPoint(DEV1, P2);
103 private static final HostLocation HOST_LOC12 = new HostLocation(CP12, 0);
104 private static final ConnectPoint CP13 = new ConnectPoint(DEV1, P3);
105 private static final HostLocation HOST_LOC13 = new HostLocation(CP13, 0);
106 private static final ConnectPoint CP21 = new ConnectPoint(DEV2, P1);
107 private static final HostLocation HOST_LOC21 = new HostLocation(CP21, 0);
108 private static final ConnectPoint CP22 = new ConnectPoint(DEV2, P2);
109 private static final HostLocation HOST_LOC22 = new HostLocation(CP22, 0);
Charles Chan65238242017-06-22 18:03:14 -0700110 // Connect Point for dual-homed host failover
111 private static final ConnectPoint CP31 = new ConnectPoint(DEV3, P1);
112 private static final HostLocation HOST_LOC31 = new HostLocation(CP31, 0);
Charles Chan8e786b52017-09-12 18:57:47 -0700113 private static final ConnectPoint CP32 = new ConnectPoint(DEV3, P2);
114 private static final HostLocation HOST_LOC32 = new HostLocation(CP32, 0);
Charles Chan65238242017-06-22 18:03:14 -0700115 private static final ConnectPoint CP41 = new ConnectPoint(DEV4, P1);
116 private static final HostLocation HOST_LOC41 = new HostLocation(CP41, 0);
117 private static final ConnectPoint CP39 = new ConnectPoint(DEV3, P9);
118 private static final ConnectPoint CP49 = new ConnectPoint(DEV4, P9);
Charles Chan9f08b102017-08-09 16:50:15 -0700119 // Conenct Point for mastership test
120 private static final ConnectPoint CP51 = new ConnectPoint(DEV5, P1);
121 private static final HostLocation HOST_LOC51 = new HostLocation(CP51, 0);
122 private static final ConnectPoint CP61 = new ConnectPoint(DEV6, P1);
123 private static final HostLocation HOST_LOC61 = new HostLocation(CP61, 0);
Charles Chanf9a52702017-06-16 15:19:24 -0700124 // Interface VLAN
Charles Chan2e2e3402017-06-19 14:00:53 -0700125 private static final VlanId INTF_VLAN_UNTAGGED = VlanId.vlanId((short) 10);
Charles Chan2e2e3402017-06-19 14:00:53 -0700126 private static final Set<VlanId> INTF_VLAN_TAGGED = Sets.newHashSet(VlanId.vlanId((short) 20));
127 private static final VlanId INTF_VLAN_NATIVE = VlanId.vlanId((short) 30);
Charles Chan65238242017-06-22 18:03:14 -0700128 private static final Set<VlanId> INTF_VLAN_PAIR = Sets.newHashSet(VlanId.vlanId((short) 10),
129 VlanId.vlanId((short) 20), VlanId.vlanId((short) 30));
Charles Chan8e786b52017-09-12 18:57:47 -0700130 private static final VlanId INTF_VLAN_OTHER = VlanId.vlanId((short) 40);
Charles Chanf9a52702017-06-16 15:19:24 -0700131 // Interface subnet
132 private static final IpPrefix INTF_PREFIX1 = IpPrefix.valueOf("10.0.1.254/24");
133 private static final IpPrefix INTF_PREFIX2 = IpPrefix.valueOf("10.0.2.254/24");
Charles Chan8e786b52017-09-12 18:57:47 -0700134 private static final IpPrefix INTF_PREFIX3 = IpPrefix.valueOf("10.0.3.254/24");
Charles Chanf9a52702017-06-16 15:19:24 -0700135 private static final InterfaceIpAddress INTF_IP1 =
136 new InterfaceIpAddress(INTF_PREFIX1.address(), INTF_PREFIX1);
137 private static final InterfaceIpAddress INTF_IP2 =
138 new InterfaceIpAddress(INTF_PREFIX2.address(), INTF_PREFIX2);
Charles Chan8e786b52017-09-12 18:57:47 -0700139 private static final InterfaceIpAddress INTF_IP3 =
140 new InterfaceIpAddress(INTF_PREFIX3.address(), INTF_PREFIX3);
Charles Chan1a3b02a2017-08-18 17:11:34 -0700141 // Interfaces
142 private static final Interface INTF11 =
143 new Interface(null, CP11, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
144 INTF_VLAN_UNTAGGED, null, null);
145 private static final Interface INTF12 =
146 new Interface(null, CP12, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
147 INTF_VLAN_UNTAGGED, null, null);
148 private static final Interface INTF13 =
149 new Interface(null, CP13, Lists.newArrayList(INTF_IP2), MacAddress.NONE, null,
150 null, INTF_VLAN_TAGGED, INTF_VLAN_NATIVE);
151 private static final Interface INTF21 =
152 new Interface(null, CP21, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
153 INTF_VLAN_UNTAGGED, null, null);
154 private static final Interface INTF22 =
155 new Interface(null, CP22, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
156 INTF_VLAN_UNTAGGED, null, null);
157 private static final Interface INTF31 =
158 new Interface(null, CP31, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
159 INTF_VLAN_UNTAGGED, null, null);
Charles Chan8e786b52017-09-12 18:57:47 -0700160 private static final Interface INTF32 =
161 new Interface(null, CP32, Lists.newArrayList(INTF_IP3), MacAddress.NONE, null,
162 INTF_VLAN_OTHER, null, null);
Charles Chan1a3b02a2017-08-18 17:11:34 -0700163 private static final Interface INTF39 =
164 new Interface(null, CP39, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
165 null, INTF_VLAN_PAIR, null);
166 private static final Interface INTF41 =
167 new Interface(null, CP41, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
168 INTF_VLAN_UNTAGGED, null, null);
169 private static final Interface INTF49 =
170 new Interface(null, CP49, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
171 null, INTF_VLAN_PAIR, null);
Charles Chanf9a52702017-06-16 15:19:24 -0700172 // Host
173 private static final Host HOST1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC,
174 HOST_VLAN_UNTAGGED, Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11),
175 false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700176
Charles Chan1a3b02a2017-08-18 17:11:34 -0700177 // A set of hosts
178 private static final Set<Host> HOSTS = Sets.newHashSet(HOST1);
179 // A set of devices of which we have mastership
180 private static final Set<DeviceId> LOCAL_DEVICES = Sets.newHashSet(DEV1, DEV2, DEV3, DEV4);
181 // A set of interfaces
182 private static final Set<Interface> INTERFACES = Sets.newHashSet(INTF11, INTF12, INTF13, INTF21,
Charles Chan8e786b52017-09-12 18:57:47 -0700183 INTF22, INTF31, INTF32, INTF39, INTF41, INTF49);
Charles Chan1a3b02a2017-08-18 17:11:34 -0700184
Charles Chan47933752017-11-30 15:37:50 -0800185 private MockLocationProbingService mockLocationProbingService;
186
Charles Chan2e2e3402017-06-19 14:00:53 -0700187 @Before
188 public void setUp() throws Exception {
Charles Chan1a3b02a2017-08-18 17:11:34 -0700189 // Initialize pairDevice and pairLocalPort config
190 ObjectMapper mapper = new ObjectMapper();
191 ConfigApplyDelegate delegate = config -> { };
192
193 SegmentRoutingDeviceConfig dev3Config = new SegmentRoutingDeviceConfig();
194 JsonNode dev3Tree = mapper.createObjectNode();
195 dev3Config.init(DEV3, "host-handler-test", dev3Tree, mapper, delegate);
196 dev3Config.setPairDeviceId(DEV4).setPairLocalPort(P9);
197
198 SegmentRoutingDeviceConfig dev4Config = new SegmentRoutingDeviceConfig();
199 JsonNode dev4Tree = mapper.createObjectNode();
200 dev4Config.init(DEV4, "host-handler-test", dev4Tree, mapper, delegate);
201 dev4Config.setPairDeviceId(DEV3).setPairLocalPort(P9);
202
203 MockNetworkConfigRegistry mockNetworkConfigRegistry = new MockNetworkConfigRegistry();
204 mockNetworkConfigRegistry.applyConfig(dev3Config);
205 mockNetworkConfigRegistry.applyConfig(dev4Config);
206
207 // Initialize Segment Routing Manager
208 SegmentRoutingManager srManager = new MockSegmentRoutingManager(NEXT_TABLE);
Charles Chan2ff1bac2018-03-29 16:03:41 -0700209 srManager.storageService = createMock(StorageService.class);
210 expect(srManager.storageService.consistentMapBuilder()).andReturn(new TestConsistentMap.Builder<>()).anyTimes();
211 replay(srManager.storageService);
Charles Chan2e2e3402017-06-19 14:00:53 -0700212 srManager.cfgService = new NetworkConfigRegistryAdapter();
213 srManager.deviceConfiguration = new DeviceConfiguration(srManager);
Charles Chan1a3b02a2017-08-18 17:11:34 -0700214 srManager.flowObjectiveService = new MockFlowObjectiveService(BRIDGING_TABLE, NEXT_TABLE);
215 srManager.routingRulePopulator = new MockRoutingRulePopulator(srManager, ROUTING_TABLE);
Charles Chanf433f952018-03-15 16:41:10 -0700216 srManager.defaultRoutingHandler = new MockDefaultRoutingHandler(srManager, SUBNET_TABLE, ROUTING_TABLE);
Charles Chan1a3b02a2017-08-18 17:11:34 -0700217 srManager.interfaceService = new MockInterfaceService(INTERFACES);
218 srManager.mastershipService = new MockMastershipService(LOCAL_DEVICES);
219 srManager.hostService = new MockHostService(HOSTS);
220 srManager.cfgService = mockNetworkConfigRegistry;
Charles Chan47933752017-11-30 15:37:50 -0800221 mockLocationProbingService = new MockLocationProbingService();
222 srManager.probingService = mockLocationProbingService;
Saurav Das45f48152018-01-18 12:07:33 -0800223 srManager.linkHandler = new MockLinkHandler(srManager);
Charles Chan2e2e3402017-06-19 14:00:53 -0700224
225 hostHandler = new HostHandler(srManager);
226
Charles Chan1a3b02a2017-08-18 17:11:34 -0700227 ROUTING_TABLE.clear();
228 BRIDGING_TABLE.clear();
Charles Chan2e2e3402017-06-19 14:00:53 -0700229 }
230
231 @Test
232 public void init() throws Exception {
Charles Chanf9a52702017-06-16 15:19:24 -0700233 hostHandler.init(DEV1);
Charles Chan1a3b02a2017-08-18 17:11:34 -0700234 assertEquals(1, ROUTING_TABLE.size());
235 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
236 assertEquals(1, BRIDGING_TABLE.size());
237 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700238
239 hostHandler.init(DEV2);
Charles Chan1a3b02a2017-08-18 17:11:34 -0700240 assertEquals(2, ROUTING_TABLE.size());
241 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
242 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
243 assertEquals(2, BRIDGING_TABLE.size());
244 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
245 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700246 }
247
248 @Test(expected = IllegalArgumentException.class)
249 public void testHostAddedAtWrongLocation() throws Exception {
250 hostHandler.processHostAddedAtLocation(HOST1, HOST_LOC13);
251 }
252
253
254 @Test()
255 public void testHostAddedAtCorrectLocation() throws Exception {
256 hostHandler.processHostAddedAtLocation(HOST1, HOST_LOC11);
Charles Chan1a3b02a2017-08-18 17:11:34 -0700257 assertEquals(1, ROUTING_TABLE.size());
258 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
259 assertEquals(1, BRIDGING_TABLE.size());
260 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700261 }
262
263 @Test
264 public void testHostAdded() throws Exception {
265 Host subject;
266
267 // Untagged host discovered on untagged port
268 // Expect: add one routing rule and one bridging rule
269 subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700270 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700271 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700272 assertEquals(1, ROUTING_TABLE.size());
273 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
274 assertEquals(1, BRIDGING_TABLE.size());
275 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700276
277 // Untagged host discovered on tagged/native port
278 // Expect: add one routing rule and one bridging rule
279 subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700280 Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP21), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700281 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700282 assertEquals(2, ROUTING_TABLE.size());
283 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
284 assertEquals(2, BRIDGING_TABLE.size());
285 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_NATIVE)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700286
287 // Tagged host discovered on untagged port
288 // Expect: ignore the host. No rule is added.
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_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700291 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700292 assertEquals(2, ROUTING_TABLE.size());
293 assertEquals(2, BRIDGING_TABLE.size());
Charles Chan2e2e3402017-06-19 14:00:53 -0700294
295 // Tagged host discovered on tagged port with the same IP
296 // Expect: update existing route, add one bridging rule
297 subject = new DefaultHost(PROVIDER_ID, HOST_ID_TAGGED, HOST_MAC, HOST_VLAN_TAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700298 Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP21), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700299 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700300 assertEquals(2, ROUTING_TABLE.size());
301 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
302 assertEquals(HOST_VLAN_TAGGED, ROUTING_TABLE.get(new MockRoutingTableKey(HOST_LOC13.deviceId(),
Charles Chanf9a52702017-06-16 15:19:24 -0700303 HOST_IP21.toIpPrefix())).vlanId);
Charles Chan1a3b02a2017-08-18 17:11:34 -0700304 assertEquals(3, BRIDGING_TABLE.size());
305 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, HOST_VLAN_TAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700306 }
307
308 @Test
309 public void testDualHomedHostAdded() throws Exception {
310 // Add a dual-homed host that has 2 locations
311 // Expect: add two routing rules and two bridging rules
312 Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
313 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
314 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700315 assertEquals(2, ROUTING_TABLE.size());
316 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
317 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
318 assertEquals(2, BRIDGING_TABLE.size());
319 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
320 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700321 }
322
323 @Test
Charles Chan8e786b52017-09-12 18:57:47 -0700324 public void testSingleHomedHostAddedOnPairLeaf() throws Exception {
325 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
326 Sets.newHashSet(HOST_LOC32), Sets.newHashSet(HOST_IP32), false);
327
328 // Add a single-homed host with one location
329 // Expect: the pair link should not be utilized
330 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
331 assertEquals(1, ROUTING_TABLE.size());
332 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP32.toIpPrefix())).portNumber);
333 assertEquals(1, BRIDGING_TABLE.size());
334 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_OTHER)).portNumber);
335 }
336
337 @Test
338 public void testDualHomedHostAddedOneByOne() throws Exception {
339 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
340 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11), false);
341 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
342 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
343
344 // Add a dual-homed host with one location
345 // Expect: the pair link is utilized temporarily before the second location is discovered
346 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
347 assertEquals(2, ROUTING_TABLE.size());
348 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
349 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
350 assertEquals(2, BRIDGING_TABLE.size());
351 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
352 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan47933752017-11-30 15:37:50 -0800353 // Expect probe to be sent out on pair device
354 assertTrue(mockLocationProbingService.verifyProbe(host1, CP41, HostLocationProbingService.ProbeMode.DISCOVER));
Charles Chan8e786b52017-09-12 18:57:47 -0700355
356 // Add the second location of dual-homed host
357 // Expect: no longer use the pair link
358 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
359 assertEquals(2, ROUTING_TABLE.size());
360 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
Charles Chan50bb6ef2018-04-18 18:41:05 -0700361 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
Charles Chan8e786b52017-09-12 18:57:47 -0700362 assertEquals(2, BRIDGING_TABLE.size());
363 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
364 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
365 }
366
367 @Test
Charles Chan2e2e3402017-06-19 14:00:53 -0700368 public void testHostRemoved() throws Exception {
369 Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700370 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700371
372 // Add a host
373 // Expect: add one routing rule and one bridging rule
374 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700375 assertEquals(1, ROUTING_TABLE.size());
376 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
377 assertEquals(1, BRIDGING_TABLE.size());
378 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700379
380 // Remove the host
381 // Expect: add the routing rule and the bridging rule
Charles Chanf9a52702017-06-16 15:19:24 -0700382 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, subject));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700383 assertEquals(0, ROUTING_TABLE.size());
384 assertEquals(0, BRIDGING_TABLE.size());
Charles Chanf9a52702017-06-16 15:19:24 -0700385 }
386
387 @Test
388 public void testDualHomedHostRemoved() throws Exception {
389 // Add a dual-homed host that has 2 locations
390 // Expect: add two routing rules and two bridging rules
391 Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
392 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
393 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700394 assertEquals(2, ROUTING_TABLE.size());
395 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
396 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
397 assertEquals(2, BRIDGING_TABLE.size());
398 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
399 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700400
401 // Remove a dual-homed host that has 2 locations
402 // Expect: all routing and bridging rules are removed
403 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, subject));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700404 assertEquals(0, ROUTING_TABLE.size());
405 assertEquals(0, BRIDGING_TABLE.size());
Charles Chan2e2e3402017-06-19 14:00:53 -0700406 }
407
408 @Test
409 public void testHostMoved() throws Exception {
410 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700411 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700412 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700413 Sets.newHashSet(HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700414 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700415 Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700416
417 // Add a host
Charles Chan65238242017-06-22 18:03:14 -0700418 // Expect: add one new routing rule, one new bridging rule
Charles Chan2e2e3402017-06-19 14:00:53 -0700419 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700420 assertEquals(1, ROUTING_TABLE.size());
421 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
422 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
423 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())));
424 assertEquals(1, BRIDGING_TABLE.size());
425 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
426 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700427
Charles Chanf9a52702017-06-16 15:19:24 -0700428 // Move the host to CP13, which has different subnet setting
Charles Chan2e2e3402017-06-19 14:00:53 -0700429 // Expect: remove routing rule. Change vlan in bridging rule.
Charles Chanf9a52702017-06-16 15:19:24 -0700430 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700431 assertEquals(0, ROUTING_TABLE.size());
432 assertEquals(1, BRIDGING_TABLE.size());
433 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_NATIVE)));
434 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700435
Charles Chanf9a52702017-06-16 15:19:24 -0700436 // Move the host to CP21, which has same subnet setting
Charles Chan2e2e3402017-06-19 14:00:53 -0700437 // Expect: add a new routing rule. Change vlan in bridging rule.
Charles Chanf9a52702017-06-16 15:19:24 -0700438 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host3));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700439 assertEquals(1, ROUTING_TABLE.size());
440 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
441 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
442 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
443 assertEquals(1, BRIDGING_TABLE.size());
444 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
445 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700446 }
447
448 @Test
449 public void testDualHomedHostMoved() throws Exception {
450 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
451 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
452 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
453 Sets.newHashSet(HOST_LOC12, HOST_LOC22), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
454 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
455 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP13, HOST_IP14), false);
456 Host host4 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
457 Sets.newHashSet(HOST_LOC11, HOST_LOC22), Sets.newHashSet(HOST_IP12, HOST_IP13), false);
Charles Chan9bd0e5a2018-04-25 18:51:46 -0400458 Host host5 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
459 Sets.newHashSet(HOST_LOC12, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
460
Charles Chanf9a52702017-06-16 15:19:24 -0700461
462 // Add a host with IP11, IP12 and LOC11, LOC21
463 // Expect: 4 routing rules and 2 bridging rules
464 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700465 assertEquals(4, ROUTING_TABLE.size());
466 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
467 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
468 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
469 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
470 assertEquals(2, BRIDGING_TABLE.size());
471 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
472 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanf9a52702017-06-16 15:19:24 -0700473
Charles Chan9bd0e5a2018-04-25 18:51:46 -0400474 // Move the host to LOC12, LOC21 and keep the IP
475 // Expect: 4 routing rules and 2 bridging rules all at the new location
476 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host5, host1));
477 assertEquals(4, ROUTING_TABLE.size());
478 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
479 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
480 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
481 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
482 assertEquals(2, BRIDGING_TABLE.size());
483 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
484 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
485
Charles Chanf9a52702017-06-16 15:19:24 -0700486 // Move the host to LOC12, LOC22 and keep the IP
487 // Expect: 4 routing rules and 2 bridging rules all at the new location
Charles Chan9bd0e5a2018-04-25 18:51:46 -0400488 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host5));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700489 assertEquals(4, ROUTING_TABLE.size());
490 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
491 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
492 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
493 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
494 assertEquals(2, BRIDGING_TABLE.size());
495 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
496 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanf9a52702017-06-16 15:19:24 -0700497
498 // Move the host to LOC11, LOC21 and change the IP to IP13, IP14 at the same time
499 // Expect: 4 routing rules and 2 bridging rules all at the new location
500 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700501 assertEquals(4, ROUTING_TABLE.size());
502 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())).portNumber);
503 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP14.toIpPrefix())).portNumber);
504 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())).portNumber);
505 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP14.toIpPrefix())).portNumber);
506 assertEquals(2, BRIDGING_TABLE.size());
507 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
508 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanf9a52702017-06-16 15:19:24 -0700509
510 // Move the host to LOC11, LOC22 and change the IP to IP12, IP13 at the same time
511 // Expect: 4 routing rules and 2 bridging rules all at the new location
512 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host4, host3));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700513 assertEquals(4, ROUTING_TABLE.size());
514 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
515 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())).portNumber);
516 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
517 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())).portNumber);
518 assertEquals(2, BRIDGING_TABLE.size());
519 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
520 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan2e2e3402017-06-19 14:00:53 -0700521 }
522
523 @Test
Charles Chan9f08b102017-08-09 16:50:15 -0700524 public void testHostMoveToInvalidLocation() throws Exception {
525 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
526 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
527 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
528 Sets.newHashSet(HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
529
530 // Add a host
531 // Expect: add one new routing rule, one new bridging rule
532 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700533 assertEquals(1, ROUTING_TABLE.size());
534 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
535 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
536 assertEquals(1, BRIDGING_TABLE.size());
537 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
538 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan9f08b102017-08-09 16:50:15 -0700539
540 // Move the host to an invalid location
541 // Expect: Old flow is removed. New flow is not created
542 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700543 assertEquals(0, ROUTING_TABLE.size());
544 assertEquals(0, BRIDGING_TABLE.size());
Charles Chan9f08b102017-08-09 16:50:15 -0700545
546 // Move the host to a valid location
547 // Expect: add one new routing rule, one new bridging rule
548 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700549 assertEquals(1, ROUTING_TABLE.size());
550 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
551 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
552 assertEquals(1, BRIDGING_TABLE.size());
553 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
554 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan9f08b102017-08-09 16:50:15 -0700555 }
556
557 @Test
558 public void testDualHomedHostMoveToInvalidLocation() throws Exception {
559 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
560 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
561 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
562 Sets.newHashSet(HOST_LOC11, HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
563 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
564 Sets.newHashSet(HOST_LOC61, HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
565
566 // Add a host
567 // Expect: add two new routing rules, two new bridging rules
568 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700569 assertEquals(2, ROUTING_TABLE.size());
570 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
571 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
572 assertEquals(2, BRIDGING_TABLE.size());
573 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
574 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan9f08b102017-08-09 16:50:15 -0700575
576 // Move first host location to an invalid location
577 // Expect: One routing and one bridging flow
578 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700579 assertEquals(1, ROUTING_TABLE.size());
580 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
581 assertEquals(1, BRIDGING_TABLE.size());
582 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan9f08b102017-08-09 16:50:15 -0700583
584 // Move second host location to an invalid location
585 // Expect: No routing or bridging rule
586 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700587 assertEquals(0, ROUTING_TABLE.size());
588 assertEquals(0, BRIDGING_TABLE.size());
Charles Chan9f08b102017-08-09 16:50:15 -0700589
590 // Move second host location back to a valid location
591 // Expect: One routing and one bridging flow
592 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host3));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700593 assertEquals(1, ROUTING_TABLE.size());
594 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
595 assertEquals(1, BRIDGING_TABLE.size());
596 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan9f08b102017-08-09 16:50:15 -0700597
598 // Move first host location back to a valid location
599 // Expect: Two routing and two bridging flow
600 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700601 assertEquals(2, ROUTING_TABLE.size());
602 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
603 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
604 assertEquals(2, BRIDGING_TABLE.size());
605 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
606 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan9f08b102017-08-09 16:50:15 -0700607 }
608
609 @Test
Charles Chan65238242017-06-22 18:03:14 -0700610 public void testDualHomingSingleLocationFail() throws Exception {
611 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
612 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
613 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
614 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
615
616 // Add a host
617 // Expect: add four new routing rules, two new bridging rules
618 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700619 assertEquals(4, ROUTING_TABLE.size());
620 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
621 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
622 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
623 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
624 assertEquals(2, BRIDGING_TABLE.size());
625 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
626 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan65238242017-06-22 18:03:14 -0700627
628 // Host becomes single-homed
629 // Expect: redirect flows from host location to pair link
630 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700631 assertEquals(4, ROUTING_TABLE.size());
632 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
633 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
634 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
635 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
636 assertEquals(2, BRIDGING_TABLE.size());
637 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
638 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan65238242017-06-22 18:03:14 -0700639
640 // Host becomes dual-homed again
641 // Expect: Redirect flows from pair link back to host location
642 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700643 assertEquals(4, ROUTING_TABLE.size());
644 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
645 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
Charles Chan47933752017-11-30 15:37:50 -0800646 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
647 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
Charles Chan50bb6ef2018-04-18 18:41:05 -0700648 assertEquals(2, BRIDGING_TABLE.size());
649 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan1a3b02a2017-08-18 17:11:34 -0700650 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan65238242017-06-22 18:03:14 -0700651 }
652
653 @Test
654 public void testDualHomingBothLocationFail() throws Exception {
655 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
656 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
657 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
658 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
659
660 // Add a host
661 // Expect: add four new routing rules, two new bridging rules
662 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan1a3b02a2017-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(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
667 assertEquals(P1, 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(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan65238242017-06-22 18:03:14 -0700671
672 // Host becomes single-homed
673 // Expect: redirect flows from host location to pair link
674 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700675 assertEquals(4, ROUTING_TABLE.size());
676 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
677 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
678 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
679 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
680 assertEquals(2, BRIDGING_TABLE.size());
681 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
682 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan65238242017-06-22 18:03:14 -0700683
684 // Host loses both locations
685 // Expect: Remove last location and all previous redirection flows
686 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, host2));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700687 assertEquals(0, ROUTING_TABLE.size());
688 assertEquals(0, BRIDGING_TABLE.size());
Charles Chan65238242017-06-22 18:03:14 -0700689 }
690
691 @Test
Charles Chan2e2e3402017-06-19 14:00:53 -0700692 public void testHostUpdated() throws Exception {
693 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700694 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700695 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700696 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP21), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700697 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700698 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP12), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700699
700 // Add a host
Charles Chanf9a52702017-06-16 15:19:24 -0700701 // Expect: add one new routing rule. Add one new bridging rule.
Charles Chan2e2e3402017-06-19 14:00:53 -0700702 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700703 assertEquals(1, ROUTING_TABLE.size());
704 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
705 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
706 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
707 assertEquals(1, BRIDGING_TABLE.size());
708 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(HOST_LOC11.deviceId(), HOST_MAC,
709 INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700710
711 // Update the host IP to same subnet
712 // Expect: update routing rule with new IP. No change to bridging rule.
713 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700714 assertEquals(1, ROUTING_TABLE.size());
715 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
716 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
717 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
718 assertEquals(1, BRIDGING_TABLE.size());
719 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700720
721 // Update the host IP to different subnet
722 // Expect: Remove routing rule. No change to bridging rule.
723 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host3));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700724 assertEquals(0, ROUTING_TABLE.size());
725 assertEquals(1, BRIDGING_TABLE.size());
726 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700727 }
728
729 @Test
Charles Chan3d650a62017-11-20 08:46:24 -0800730 public void testDelayedIpAndLocation() throws Exception {
731 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
732 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(), false);
733 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
734 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11), false);
735 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
736 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
737
738 // Add a dual-home host with only one location and no IP
739 // Expect: only bridging redirection works
740 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
741 assertEquals(0, ROUTING_TABLE.size());
742 assertEquals(2, BRIDGING_TABLE.size());
743 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
744 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
745
746 // Discover IP
747 // Expect: routing redirection should also work
Charles Chan47933752017-11-30 15:37:50 -0800748 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host1));
Charles Chan3d650a62017-11-20 08:46:24 -0800749 assertEquals(2, ROUTING_TABLE.size());
750 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
751 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
752 assertEquals(2, BRIDGING_TABLE.size());
753 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
754 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan47933752017-11-30 15:37:50 -0800755 // Expect probe to be sent out on pair device
756 assertTrue(mockLocationProbingService.verifyProbe(host2, CP41, HostLocationProbingService.ProbeMode.DISCOVER));
Charles Chan3d650a62017-11-20 08:46:24 -0800757
758 // Discover location
759 // Expect: cancel all redirections
Charles Chan47933752017-11-30 15:37:50 -0800760 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
Charles Chan3d650a62017-11-20 08:46:24 -0800761 assertEquals(2, ROUTING_TABLE.size());
762 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
Charles Chan50bb6ef2018-04-18 18:41:05 -0700763 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
Charles Chan3d650a62017-11-20 08:46:24 -0800764 assertEquals(2, BRIDGING_TABLE.size());
765 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan50bb6ef2018-04-18 18:41:05 -0700766 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan47933752017-11-30 15:37:50 -0800767 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
Charles Chan3d650a62017-11-20 08:46:24 -0800768 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
769 }
770
771 @Test
772 public void testDelayedIpAndLocation2() throws Exception {
773 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
774 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(), false);
775 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
776 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(), false);
777 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
778 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
779
780 // Add a dual-home host with only one location and no IP
781 // Expect: only bridging redirection works
782 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
783 assertEquals(0, ROUTING_TABLE.size());
784 assertEquals(2, BRIDGING_TABLE.size());
785 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
786 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
787
788 // Discover Location
789 // Expect: cancel bridging redirections
790 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
791 assertEquals(0, ROUTING_TABLE.size());
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 // Discover IP
797 // Expect: add IP rules to both location
798 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host2));
799 assertEquals(2, ROUTING_TABLE.size());
800 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
801 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
802 assertEquals(2, BRIDGING_TABLE.size());
803 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
804 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
805 }
806
807 @Test
Charles Chanf9a52702017-06-16 15:19:24 -0700808 public void testDualHomedHostUpdated() throws Exception {
809 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
810 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
811 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
812 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP21), false);
813 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
814 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP13, HOST_IP14), false);
815
816 // Add a dual-homed host with two locations and two IPs
817 // Expect: add four new routing rules. Add two new bridging rules
818 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700819 assertEquals(4, ROUTING_TABLE.size());
820 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
821 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
822 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
823 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
824 assertEquals(2, BRIDGING_TABLE.size());
825 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
826 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700827
828 // Update both host IPs
829 // Expect: update routing rules with new IP. No change to bridging rule.
830 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700831 assertEquals(4, ROUTING_TABLE.size());
832 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
833 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
834 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())));
835 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP14.toIpPrefix())));
836 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
837 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
838 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())));
839 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP14.toIpPrefix())));
840 assertEquals(2, BRIDGING_TABLE.size());
841 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
842 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700843
844 // Update one of the host IP to different subnet
845 // Expect: update routing rule with new IP. No change to bridging rule.
846 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host3));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700847 assertEquals(2, ROUTING_TABLE.size());
848 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
849 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
850 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
851 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
852 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP21.toIpPrefix())));
853 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
854 assertEquals(2, BRIDGING_TABLE.size());
855 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
856 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700857 }
Ray Milkeyfacf2862017-08-03 11:58:29 -0700858}