blob: fd263bf21a9efbc89bb078c214ee04a01d843ffc [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;
Charles Chan4d639392018-06-21 19:07:12 -070024import org.easymock.EasyMock;
Charles Chan2e2e3402017-06-19 14:00:53 -070025import org.junit.Before;
26import org.junit.Test;
27import org.onlab.packet.IpAddress;
28import org.onlab.packet.IpPrefix;
29import org.onlab.packet.MacAddress;
30import org.onlab.packet.VlanId;
Charles Chan1a3b02a2017-08-18 17:11:34 -070031import org.onosproject.net.config.ConfigApplyDelegate;
Charles Chanf82d1552018-07-23 15:27:34 -070032import org.onosproject.net.host.HostProbingService;
Charles Chanff79dd92018-06-01 16:33:48 -070033import org.onosproject.net.host.ProbeMode;
Ray Milkeyfacf2862017-08-03 11:58:29 -070034import org.onosproject.net.intf.Interface;
Charles Chan2e2e3402017-06-19 14:00:53 -070035import org.onosproject.net.ConnectPoint;
36import org.onosproject.net.DefaultHost;
37import org.onosproject.net.DeviceId;
38import org.onosproject.net.Host;
39import org.onosproject.net.HostId;
40import org.onosproject.net.HostLocation;
41import org.onosproject.net.PortNumber;
42import org.onosproject.net.config.NetworkConfigRegistryAdapter;
Charles Chan2e2e3402017-06-19 14:00:53 -070043import org.onosproject.net.flow.TrafficTreatment;
Charles Chan2e2e3402017-06-19 14:00:53 -070044import org.onosproject.net.host.HostEvent;
45import org.onosproject.net.host.InterfaceIpAddress;
46import org.onosproject.net.provider.ProviderId;
Charles Chan4d639392018-06-21 19:07:12 -070047import org.onosproject.routeservice.ResolvedRoute;
48import org.onosproject.routeservice.Route;
49import org.onosproject.routeservice.RouteInfo;
50import org.onosproject.routeservice.RouteService;
51import org.onosproject.routeservice.RouteTableId;
Charles Chan2e2e3402017-06-19 14:00:53 -070052import org.onosproject.segmentrouting.config.DeviceConfiguration;
Charles Chan65238242017-06-22 18:03:14 -070053import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
Charles Chan2ff1bac2018-03-29 16:03:41 -070054import org.onosproject.store.service.StorageService;
55import org.onosproject.store.service.TestConsistentMap;
Charles Chan2e2e3402017-06-19 14:00:53 -070056
57import java.util.Map;
Charles Chan2e2e3402017-06-19 14:00:53 -070058import java.util.Set;
Charles Chan2e2e3402017-06-19 14:00:53 -070059
Charles Chan2ff1bac2018-03-29 16:03:41 -070060import static org.easymock.EasyMock.createMock;
Charles Chan4d639392018-06-21 19:07:12 -070061import static org.easymock.EasyMock.createNiceMock;
Charles Chan2ff1bac2018-03-29 16:03:41 -070062import static org.easymock.EasyMock.expect;
Charles Chan4d639392018-06-21 19:07:12 -070063import static org.easymock.EasyMock.expectLastCall;
Charles Chan2ff1bac2018-03-29 16:03:41 -070064import static org.easymock.EasyMock.replay;
Charles Chan4d639392018-06-21 19:07:12 -070065import static org.easymock.EasyMock.reset;
66import static org.easymock.EasyMock.verify;
Charles Chan2e2e3402017-06-19 14:00:53 -070067import static org.junit.Assert.*;
68
Charles Chan1a3b02a2017-08-18 17:11:34 -070069/**r
Charles Chan2e2e3402017-06-19 14:00:53 -070070 * Unit test for {@link HostHandler}.
71 */
72public class HostHandlerTest {
Charles Chan2e2e3402017-06-19 14:00:53 -070073 private HostHandler hostHandler;
74
75 // Mocked routing and bridging tables
Charles Chan1a3b02a2017-08-18 17:11:34 -070076 private static final Map<MockBridgingTableKey, MockBridgingTableValue> BRIDGING_TABLE =
77 Maps.newConcurrentMap();
78 private static final Map<MockRoutingTableKey, MockRoutingTableValue> ROUTING_TABLE =
79 Maps.newConcurrentMap();
Charles Chan2fde6d42017-08-23 14:46:43 -070080 private static final Map<ConnectPoint, Set<IpPrefix>> SUBNET_TABLE = Maps.newConcurrentMap();
Charles Chan2e2e3402017-06-19 14:00:53 -070081 // Mocked Next Id
Charles Chan1a3b02a2017-08-18 17:11:34 -070082 private static final Map<Integer, TrafficTreatment> NEXT_TABLE = Maps.newConcurrentMap();
Charles Chan2e2e3402017-06-19 14:00:53 -070083
Charles Chanf9a52702017-06-16 15:19:24 -070084 // Host Mac, VLAN
Charles Chan2e2e3402017-06-19 14:00:53 -070085 private static final ProviderId PROVIDER_ID = ProviderId.NONE;
86 private static final MacAddress HOST_MAC = MacAddress.valueOf("00:00:00:00:00:01");
87 private static final VlanId HOST_VLAN_UNTAGGED = VlanId.NONE;
88 private static final HostId HOST_ID_UNTAGGED = HostId.hostId(HOST_MAC, HOST_VLAN_UNTAGGED);
89 private static final VlanId HOST_VLAN_TAGGED = VlanId.vlanId((short) 20);
90 private static final HostId HOST_ID_TAGGED = HostId.hostId(HOST_MAC, HOST_VLAN_TAGGED);
Charles Chanf9a52702017-06-16 15:19:24 -070091 // Host IP
92 private static final IpAddress HOST_IP11 = IpAddress.valueOf("10.0.1.1");
93 private static final IpAddress HOST_IP21 = IpAddress.valueOf("10.0.2.1");
94 private static final IpAddress HOST_IP12 = IpAddress.valueOf("10.0.1.2");
95 private static final IpAddress HOST_IP13 = IpAddress.valueOf("10.0.1.3");
96 private static final IpAddress HOST_IP14 = IpAddress.valueOf("10.0.1.4");
Charles Chanf82d1552018-07-23 15:27:34 -070097 private static final IpAddress HOST_IP33 = IpAddress.valueOf("10.0.3.3");
Charles Chanf9a52702017-06-16 15:19:24 -070098 // Device
99 private static final DeviceId DEV1 = DeviceId.deviceId("of:0000000000000001");
100 private static final DeviceId DEV2 = DeviceId.deviceId("of:0000000000000002");
Charles Chan9f08b102017-08-09 16:50:15 -0700101 private static final DeviceId DEV3 = DeviceId.deviceId("of:0000000000000003");
102 private static final DeviceId DEV4 = DeviceId.deviceId("of:0000000000000004");
103 private static final DeviceId DEV5 = DeviceId.deviceId("of:0000000000000005");
104 private static final DeviceId DEV6 = DeviceId.deviceId("of:0000000000000006");
Charles Chanf9a52702017-06-16 15:19:24 -0700105 // Port
106 private static final PortNumber P1 = PortNumber.portNumber(1);
107 private static final PortNumber P2 = PortNumber.portNumber(2);
108 private static final PortNumber P3 = PortNumber.portNumber(3);
Charles Chan65238242017-06-22 18:03:14 -0700109 private static final PortNumber P9 = PortNumber.portNumber(9);
Charles Chanf9a52702017-06-16 15:19:24 -0700110 // Connect Point
111 private static final ConnectPoint CP11 = new ConnectPoint(DEV1, P1);
112 private static final HostLocation HOST_LOC11 = new HostLocation(CP11, 0);
113 private static final ConnectPoint CP12 = new ConnectPoint(DEV1, P2);
114 private static final HostLocation HOST_LOC12 = new HostLocation(CP12, 0);
115 private static final ConnectPoint CP13 = new ConnectPoint(DEV1, P3);
116 private static final HostLocation HOST_LOC13 = new HostLocation(CP13, 0);
117 private static final ConnectPoint CP21 = new ConnectPoint(DEV2, P1);
118 private static final HostLocation HOST_LOC21 = new HostLocation(CP21, 0);
119 private static final ConnectPoint CP22 = new ConnectPoint(DEV2, P2);
120 private static final HostLocation HOST_LOC22 = new HostLocation(CP22, 0);
Charles Chan65238242017-06-22 18:03:14 -0700121 // Connect Point for dual-homed host failover
122 private static final ConnectPoint CP31 = new ConnectPoint(DEV3, P1);
123 private static final HostLocation HOST_LOC31 = new HostLocation(CP31, 0);
Charles Chan8e786b52017-09-12 18:57:47 -0700124 private static final ConnectPoint CP32 = new ConnectPoint(DEV3, P2);
125 private static final HostLocation HOST_LOC32 = new HostLocation(CP32, 0);
Charles Chanf82d1552018-07-23 15:27:34 -0700126 private static final ConnectPoint CP33 = new ConnectPoint(DEV3, P3);
127 private static final HostLocation HOST_LOC33 = new HostLocation(CP33, 0);
Charles Chan65238242017-06-22 18:03:14 -0700128 private static final ConnectPoint CP41 = new ConnectPoint(DEV4, P1);
129 private static final HostLocation HOST_LOC41 = new HostLocation(CP41, 0);
Charles Chanf82d1552018-07-23 15:27:34 -0700130 private static final ConnectPoint CP42 = new ConnectPoint(DEV4, P2);
131 private static final HostLocation HOST_LOC42 = new HostLocation(CP42, 0);
Charles Chan65238242017-06-22 18:03:14 -0700132 private static final ConnectPoint CP39 = new ConnectPoint(DEV3, P9);
133 private static final ConnectPoint CP49 = new ConnectPoint(DEV4, P9);
Charles Chan9f08b102017-08-09 16:50:15 -0700134 // Conenct Point for mastership test
135 private static final ConnectPoint CP51 = new ConnectPoint(DEV5, P1);
136 private static final HostLocation HOST_LOC51 = new HostLocation(CP51, 0);
137 private static final ConnectPoint CP61 = new ConnectPoint(DEV6, P1);
138 private static final HostLocation HOST_LOC61 = new HostLocation(CP61, 0);
Charles Chanf9a52702017-06-16 15:19:24 -0700139 // Interface VLAN
Charles Chan2e2e3402017-06-19 14:00:53 -0700140 private static final VlanId INTF_VLAN_UNTAGGED = VlanId.vlanId((short) 10);
Charles Chanf76de302018-06-15 18:54:18 -0700141 private static final VlanId INTF_VLAN_TAGGED_1 = VlanId.vlanId((short) 20);
142 private static final Set<VlanId> INTF_VLAN_TAGGED = Sets.newHashSet(INTF_VLAN_TAGGED_1);
Charles Chan2e2e3402017-06-19 14:00:53 -0700143 private static final VlanId INTF_VLAN_NATIVE = VlanId.vlanId((short) 30);
Charles Chan65238242017-06-22 18:03:14 -0700144 private static final Set<VlanId> INTF_VLAN_PAIR = Sets.newHashSet(VlanId.vlanId((short) 10),
145 VlanId.vlanId((short) 20), VlanId.vlanId((short) 30));
Charles Chan8e786b52017-09-12 18:57:47 -0700146 private static final VlanId INTF_VLAN_OTHER = VlanId.vlanId((short) 40);
Charles Chanf9a52702017-06-16 15:19:24 -0700147 // Interface subnet
148 private static final IpPrefix INTF_PREFIX1 = IpPrefix.valueOf("10.0.1.254/24");
149 private static final IpPrefix INTF_PREFIX2 = IpPrefix.valueOf("10.0.2.254/24");
Charles Chan8e786b52017-09-12 18:57:47 -0700150 private static final IpPrefix INTF_PREFIX3 = IpPrefix.valueOf("10.0.3.254/24");
Charles Chanf9a52702017-06-16 15:19:24 -0700151 private static final InterfaceIpAddress INTF_IP1 =
152 new InterfaceIpAddress(INTF_PREFIX1.address(), INTF_PREFIX1);
153 private static final InterfaceIpAddress INTF_IP2 =
154 new InterfaceIpAddress(INTF_PREFIX2.address(), INTF_PREFIX2);
Charles Chan8e786b52017-09-12 18:57:47 -0700155 private static final InterfaceIpAddress INTF_IP3 =
156 new InterfaceIpAddress(INTF_PREFIX3.address(), INTF_PREFIX3);
Charles Chan1a3b02a2017-08-18 17:11:34 -0700157 // Interfaces
158 private static final Interface INTF11 =
159 new Interface(null, CP11, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
160 INTF_VLAN_UNTAGGED, null, null);
161 private static final Interface INTF12 =
162 new Interface(null, CP12, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
163 INTF_VLAN_UNTAGGED, null, null);
164 private static final Interface INTF13 =
165 new Interface(null, CP13, Lists.newArrayList(INTF_IP2), MacAddress.NONE, null,
166 null, INTF_VLAN_TAGGED, INTF_VLAN_NATIVE);
167 private static final Interface INTF21 =
168 new Interface(null, CP21, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
169 INTF_VLAN_UNTAGGED, null, null);
170 private static final Interface INTF22 =
171 new Interface(null, CP22, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
172 INTF_VLAN_UNTAGGED, null, null);
173 private static final Interface INTF31 =
174 new Interface(null, CP31, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
175 INTF_VLAN_UNTAGGED, null, null);
Charles Chan8e786b52017-09-12 18:57:47 -0700176 private static final Interface INTF32 =
Charles Chanf82d1552018-07-23 15:27:34 -0700177 new Interface(null, CP32, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
178 INTF_VLAN_UNTAGGED, null, null);
179 private static final Interface INTF33 =
180 new Interface(null, CP33, Lists.newArrayList(INTF_IP3), MacAddress.NONE, null,
Charles Chan8e786b52017-09-12 18:57:47 -0700181 INTF_VLAN_OTHER, null, null);
Charles Chan1a3b02a2017-08-18 17:11:34 -0700182 private static final Interface INTF39 =
183 new Interface(null, CP39, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
184 null, INTF_VLAN_PAIR, null);
185 private static final Interface INTF41 =
186 new Interface(null, CP41, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
187 INTF_VLAN_UNTAGGED, null, null);
Charles Chanf82d1552018-07-23 15:27:34 -0700188 private static final Interface INTF42 =
189 new Interface(null, CP42, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
190 INTF_VLAN_UNTAGGED, null, null);
Charles Chan1a3b02a2017-08-18 17:11:34 -0700191 private static final Interface INTF49 =
192 new Interface(null, CP49, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
193 null, INTF_VLAN_PAIR, null);
Charles Chanf9a52702017-06-16 15:19:24 -0700194 // Host
195 private static final Host HOST1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC,
196 HOST_VLAN_UNTAGGED, Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11),
197 false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700198
Charles Chan1a3b02a2017-08-18 17:11:34 -0700199 // A set of hosts
200 private static final Set<Host> HOSTS = Sets.newHashSet(HOST1);
201 // A set of devices of which we have mastership
202 private static final Set<DeviceId> LOCAL_DEVICES = Sets.newHashSet(DEV1, DEV2, DEV3, DEV4);
203 // A set of interfaces
204 private static final Set<Interface> INTERFACES = Sets.newHashSet(INTF11, INTF12, INTF13, INTF21,
Charles Chanf82d1552018-07-23 15:27:34 -0700205 INTF22, INTF31, INTF32, INTF33, INTF39, INTF41, INTF42, INTF49);
Charles Chan1a3b02a2017-08-18 17:11:34 -0700206
Charles Chanff79dd92018-06-01 16:33:48 -0700207 private MockHostProbingService mockLocationProbingService;
Charles Chan47933752017-11-30 15:37:50 -0800208
Charles Chan2e2e3402017-06-19 14:00:53 -0700209 @Before
Charles Chanf82d1552018-07-23 15:27:34 -0700210 public void setUp() {
Charles Chan1a3b02a2017-08-18 17:11:34 -0700211 // Initialize pairDevice and pairLocalPort config
212 ObjectMapper mapper = new ObjectMapper();
213 ConfigApplyDelegate delegate = config -> { };
214
215 SegmentRoutingDeviceConfig dev3Config = new SegmentRoutingDeviceConfig();
216 JsonNode dev3Tree = mapper.createObjectNode();
217 dev3Config.init(DEV3, "host-handler-test", dev3Tree, mapper, delegate);
218 dev3Config.setPairDeviceId(DEV4).setPairLocalPort(P9);
219
220 SegmentRoutingDeviceConfig dev4Config = new SegmentRoutingDeviceConfig();
221 JsonNode dev4Tree = mapper.createObjectNode();
222 dev4Config.init(DEV4, "host-handler-test", dev4Tree, mapper, delegate);
223 dev4Config.setPairDeviceId(DEV3).setPairLocalPort(P9);
224
225 MockNetworkConfigRegistry mockNetworkConfigRegistry = new MockNetworkConfigRegistry();
226 mockNetworkConfigRegistry.applyConfig(dev3Config);
227 mockNetworkConfigRegistry.applyConfig(dev4Config);
228
229 // Initialize Segment Routing Manager
230 SegmentRoutingManager srManager = new MockSegmentRoutingManager(NEXT_TABLE);
Charles Chan2ff1bac2018-03-29 16:03:41 -0700231 srManager.storageService = createMock(StorageService.class);
232 expect(srManager.storageService.consistentMapBuilder()).andReturn(new TestConsistentMap.Builder<>()).anyTimes();
233 replay(srManager.storageService);
Charles Chan2e2e3402017-06-19 14:00:53 -0700234 srManager.cfgService = new NetworkConfigRegistryAdapter();
235 srManager.deviceConfiguration = new DeviceConfiguration(srManager);
Charles Chan1a3b02a2017-08-18 17:11:34 -0700236 srManager.flowObjectiveService = new MockFlowObjectiveService(BRIDGING_TABLE, NEXT_TABLE);
237 srManager.routingRulePopulator = new MockRoutingRulePopulator(srManager, ROUTING_TABLE);
Charles Chanf433f952018-03-15 16:41:10 -0700238 srManager.defaultRoutingHandler = new MockDefaultRoutingHandler(srManager, SUBNET_TABLE, ROUTING_TABLE);
Charles Chan1a3b02a2017-08-18 17:11:34 -0700239 srManager.interfaceService = new MockInterfaceService(INTERFACES);
240 srManager.mastershipService = new MockMastershipService(LOCAL_DEVICES);
241 srManager.hostService = new MockHostService(HOSTS);
242 srManager.cfgService = mockNetworkConfigRegistry;
Charles Chanff79dd92018-06-01 16:33:48 -0700243 mockLocationProbingService = new MockHostProbingService();
Charles Chan47933752017-11-30 15:37:50 -0800244 srManager.probingService = mockLocationProbingService;
Saurav Das45f48152018-01-18 12:07:33 -0800245 srManager.linkHandler = new MockLinkHandler(srManager);
Charles Chan2e2e3402017-06-19 14:00:53 -0700246
Charles Chan4d639392018-06-21 19:07:12 -0700247 // Not important for most of the HostHandler test case. Simply return an empty set here
248 srManager.routeService = createNiceMock(RouteService.class);
249 expect(srManager.routeService.getRouteTables()).andReturn(Sets.newHashSet()).anyTimes();
250 replay(srManager.routeService);
251
Charles Chan2e2e3402017-06-19 14:00:53 -0700252 hostHandler = new HostHandler(srManager);
253
Charles Chan1a3b02a2017-08-18 17:11:34 -0700254 ROUTING_TABLE.clear();
255 BRIDGING_TABLE.clear();
Charles Chan2e2e3402017-06-19 14:00:53 -0700256 }
257
258 @Test
Charles Chanf82d1552018-07-23 15:27:34 -0700259 public void init() {
Charles Chanf9a52702017-06-16 15:19:24 -0700260 hostHandler.init(DEV1);
Charles Chan1a3b02a2017-08-18 17:11:34 -0700261 assertEquals(1, ROUTING_TABLE.size());
262 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
263 assertEquals(1, BRIDGING_TABLE.size());
264 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700265
266 hostHandler.init(DEV2);
Charles Chan1a3b02a2017-08-18 17:11:34 -0700267 assertEquals(2, ROUTING_TABLE.size());
268 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
269 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
270 assertEquals(2, BRIDGING_TABLE.size());
271 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
272 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700273 }
274
275 @Test(expected = IllegalArgumentException.class)
Charles Chanf82d1552018-07-23 15:27:34 -0700276 public void testHostAddedAtWrongLocation() {
Charles Chanf9a52702017-06-16 15:19:24 -0700277 hostHandler.processHostAddedAtLocation(HOST1, HOST_LOC13);
278 }
279
280
281 @Test()
Charles Chanf82d1552018-07-23 15:27:34 -0700282 public void testHostAddedAtCorrectLocation() {
Charles Chanf9a52702017-06-16 15:19:24 -0700283 hostHandler.processHostAddedAtLocation(HOST1, HOST_LOC11);
Charles Chan1a3b02a2017-08-18 17:11:34 -0700284 assertEquals(1, ROUTING_TABLE.size());
285 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
286 assertEquals(1, BRIDGING_TABLE.size());
287 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700288 }
289
290 @Test
Charles Chanf82d1552018-07-23 15:27:34 -0700291 public void testHostAdded() {
Charles Chan2e2e3402017-06-19 14:00:53 -0700292 Host subject;
293
294 // Untagged host discovered on untagged port
295 // Expect: add one routing rule and one bridging rule
296 subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700297 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700298 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700299 assertEquals(1, ROUTING_TABLE.size());
300 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
301 assertEquals(1, BRIDGING_TABLE.size());
302 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700303
304 // Untagged host discovered on tagged/native port
305 // Expect: add one routing rule and one bridging rule
306 subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700307 Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP21), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700308 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700309 assertEquals(2, ROUTING_TABLE.size());
310 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
311 assertEquals(2, BRIDGING_TABLE.size());
312 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_NATIVE)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700313
314 // Tagged host discovered on untagged port
315 // Expect: ignore the host. No rule is added.
316 subject = new DefaultHost(PROVIDER_ID, HOST_ID_TAGGED, HOST_MAC, HOST_VLAN_TAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700317 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700318 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700319 assertEquals(2, ROUTING_TABLE.size());
320 assertEquals(2, BRIDGING_TABLE.size());
Charles Chan2e2e3402017-06-19 14:00:53 -0700321
322 // Tagged host discovered on tagged port with the same IP
323 // Expect: update existing route, add one bridging rule
324 subject = new DefaultHost(PROVIDER_ID, HOST_ID_TAGGED, HOST_MAC, HOST_VLAN_TAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700325 Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP21), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700326 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700327 assertEquals(2, ROUTING_TABLE.size());
328 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
329 assertEquals(HOST_VLAN_TAGGED, ROUTING_TABLE.get(new MockRoutingTableKey(HOST_LOC13.deviceId(),
Charles Chanf9a52702017-06-16 15:19:24 -0700330 HOST_IP21.toIpPrefix())).vlanId);
Charles Chan1a3b02a2017-08-18 17:11:34 -0700331 assertEquals(3, BRIDGING_TABLE.size());
332 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, HOST_VLAN_TAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700333 }
334
335 @Test
Charles Chanf82d1552018-07-23 15:27:34 -0700336 public void testDualHomedHostAdded() {
Charles Chanf9a52702017-06-16 15:19:24 -0700337 // Add a dual-homed host that has 2 locations
338 // Expect: add two routing rules and two bridging rules
339 Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
340 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
341 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700342 assertEquals(2, ROUTING_TABLE.size());
343 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
344 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
345 assertEquals(2, BRIDGING_TABLE.size());
346 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
347 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700348 }
349
350 @Test
Charles Chanf82d1552018-07-23 15:27:34 -0700351 public void testSingleHomedHostAddedOnPairLeaf() {
Charles Chan8e786b52017-09-12 18:57:47 -0700352 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf82d1552018-07-23 15:27:34 -0700353 Sets.newHashSet(HOST_LOC33), Sets.newHashSet(HOST_IP33), false);
Charles Chan8e786b52017-09-12 18:57:47 -0700354
355 // Add a single-homed host with one location
356 // Expect: the pair link should not be utilized
357 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
358 assertEquals(1, ROUTING_TABLE.size());
Charles Chanf82d1552018-07-23 15:27:34 -0700359 assertEquals(P3, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP33.toIpPrefix())).portNumber);
Charles Chan8e786b52017-09-12 18:57:47 -0700360 assertEquals(1, BRIDGING_TABLE.size());
Charles Chanf82d1552018-07-23 15:27:34 -0700361 assertEquals(P3, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_OTHER)).portNumber);
Charles Chan8e786b52017-09-12 18:57:47 -0700362 }
363
364 @Test
Charles Chanf82d1552018-07-23 15:27:34 -0700365 public void testDualHomedHostAddedOneByOne() {
Charles Chan8e786b52017-09-12 18:57:47 -0700366 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
367 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11), false);
368 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
369 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
370
371 // Add a dual-homed host with one location
372 // Expect: the pair link is utilized temporarily before the second location is discovered
373 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
374 assertEquals(2, ROUTING_TABLE.size());
375 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
376 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
377 assertEquals(2, BRIDGING_TABLE.size());
378 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
379 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan47933752017-11-30 15:37:50 -0800380 // Expect probe to be sent out on pair device
Charles Chanff79dd92018-06-01 16:33:48 -0700381 assertTrue(mockLocationProbingService.verifyProbe(host1, CP41, ProbeMode.DISCOVER));
Charles Chan8e786b52017-09-12 18:57:47 -0700382
383 // Add the second location of dual-homed host
384 // Expect: no longer use the pair link
385 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
386 assertEquals(2, ROUTING_TABLE.size());
387 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
Charles Chan50bb6ef2018-04-18 18:41:05 -0700388 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
Charles Chan8e786b52017-09-12 18:57:47 -0700389 assertEquals(2, BRIDGING_TABLE.size());
390 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
391 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
392 }
393
394 @Test
Charles Chanf82d1552018-07-23 15:27:34 -0700395 public void testHostRemoved() {
Charles Chan2e2e3402017-06-19 14:00:53 -0700396 Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700397 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700398
399 // Add a host
400 // Expect: add one routing rule and one bridging rule
401 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700402 assertEquals(1, ROUTING_TABLE.size());
403 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
404 assertEquals(1, BRIDGING_TABLE.size());
405 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700406
407 // Remove the host
408 // Expect: add the routing rule and the bridging rule
Charles Chanf9a52702017-06-16 15:19:24 -0700409 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, subject));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700410 assertEquals(0, ROUTING_TABLE.size());
411 assertEquals(0, BRIDGING_TABLE.size());
Charles Chanf9a52702017-06-16 15:19:24 -0700412 }
413
414 @Test
Charles Chanf82d1552018-07-23 15:27:34 -0700415 public void testDualHomedHostRemoved() {
Charles Chanf9a52702017-06-16 15:19:24 -0700416 // Add a dual-homed host that has 2 locations
417 // Expect: add two routing rules and two bridging rules
418 Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
419 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
420 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700421 assertEquals(2, ROUTING_TABLE.size());
422 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
423 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
424 assertEquals(2, BRIDGING_TABLE.size());
425 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
426 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700427
428 // Remove a dual-homed host that has 2 locations
429 // Expect: all routing and bridging rules are removed
430 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, subject));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700431 assertEquals(0, ROUTING_TABLE.size());
432 assertEquals(0, BRIDGING_TABLE.size());
Charles Chan2e2e3402017-06-19 14:00:53 -0700433 }
434
435 @Test
Charles Chanf82d1552018-07-23 15:27:34 -0700436 public void testHostMoved() {
Charles Chan2e2e3402017-06-19 14:00:53 -0700437 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700438 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700439 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700440 Sets.newHashSet(HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700441 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700442 Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700443
444 // Add a host
Charles Chan65238242017-06-22 18:03:14 -0700445 // Expect: add one new routing rule, one new bridging rule
Charles Chan2e2e3402017-06-19 14:00:53 -0700446 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700447 assertEquals(1, ROUTING_TABLE.size());
448 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
449 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
450 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())));
451 assertEquals(1, BRIDGING_TABLE.size());
452 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
453 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700454
Charles Chanf9a52702017-06-16 15:19:24 -0700455 // Move the host to CP13, which has different subnet setting
Charles Chan2e2e3402017-06-19 14:00:53 -0700456 // Expect: remove routing rule. Change vlan in bridging rule.
Charles Chanf9a52702017-06-16 15:19:24 -0700457 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700458 assertEquals(0, ROUTING_TABLE.size());
459 assertEquals(1, BRIDGING_TABLE.size());
460 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_NATIVE)));
461 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700462
Charles Chanf9a52702017-06-16 15:19:24 -0700463 // Move the host to CP21, which has same subnet setting
Charles Chan2e2e3402017-06-19 14:00:53 -0700464 // Expect: add a new routing rule. Change vlan in bridging rule.
Charles Chanf9a52702017-06-16 15:19:24 -0700465 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host3));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700466 assertEquals(1, ROUTING_TABLE.size());
467 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
468 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
469 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
470 assertEquals(1, BRIDGING_TABLE.size());
471 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
472 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700473 }
474
475 @Test
Charles Chanf82d1552018-07-23 15:27:34 -0700476 public void testDualHomedHostMoved() {
Charles Chanf9a52702017-06-16 15:19:24 -0700477 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
478 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
479 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
480 Sets.newHashSet(HOST_LOC12, HOST_LOC22), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
481 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
482 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP13, HOST_IP14), false);
483 Host host4 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
484 Sets.newHashSet(HOST_LOC11, HOST_LOC22), Sets.newHashSet(HOST_IP12, HOST_IP13), false);
Charles Chan9bd0e5a2018-04-25 18:51:46 -0400485 Host host5 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
486 Sets.newHashSet(HOST_LOC12, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
487
Charles Chanf9a52702017-06-16 15:19:24 -0700488
489 // Add a host with IP11, IP12 and LOC11, LOC21
490 // Expect: 4 routing rules and 2 bridging rules
491 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700492 assertEquals(4, ROUTING_TABLE.size());
493 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
494 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
495 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
496 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
497 assertEquals(2, BRIDGING_TABLE.size());
498 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
499 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanf9a52702017-06-16 15:19:24 -0700500
Charles Chan9bd0e5a2018-04-25 18:51:46 -0400501 // Move the host to LOC12, LOC21 and keep the IP
502 // Expect: 4 routing rules and 2 bridging rules all at the new location
503 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host5, host1));
504 assertEquals(4, ROUTING_TABLE.size());
505 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
506 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
507 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
508 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
509 assertEquals(2, BRIDGING_TABLE.size());
510 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
511 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
512
Charles Chanf9a52702017-06-16 15:19:24 -0700513 // Move the host to LOC12, LOC22 and keep the IP
514 // Expect: 4 routing rules and 2 bridging rules all at the new location
Charles Chan9bd0e5a2018-04-25 18:51:46 -0400515 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host5));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700516 assertEquals(4, ROUTING_TABLE.size());
517 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
518 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
519 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
520 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
521 assertEquals(2, BRIDGING_TABLE.size());
522 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
523 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanf9a52702017-06-16 15:19:24 -0700524
525 // Move the host to LOC11, LOC21 and change the IP to IP13, IP14 at the same time
526 // Expect: 4 routing rules and 2 bridging rules all at the new location
527 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700528 assertEquals(4, ROUTING_TABLE.size());
529 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())).portNumber);
530 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP14.toIpPrefix())).portNumber);
531 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())).portNumber);
532 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP14.toIpPrefix())).portNumber);
533 assertEquals(2, BRIDGING_TABLE.size());
534 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
535 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanf9a52702017-06-16 15:19:24 -0700536
537 // Move the host to LOC11, LOC22 and change the IP to IP12, IP13 at the same time
538 // Expect: 4 routing rules and 2 bridging rules all at the new location
539 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host4, host3));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700540 assertEquals(4, ROUTING_TABLE.size());
541 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
542 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())).portNumber);
543 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
544 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())).portNumber);
545 assertEquals(2, BRIDGING_TABLE.size());
546 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
547 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan2e2e3402017-06-19 14:00:53 -0700548 }
549
550 @Test
Charles Chanf82d1552018-07-23 15:27:34 -0700551 public void testHostMoveToInvalidLocation() {
Charles Chan9f08b102017-08-09 16:50:15 -0700552 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
553 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
554 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
555 Sets.newHashSet(HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
556
557 // Add a host
558 // Expect: add one new routing rule, one new bridging rule
559 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700560 assertEquals(1, ROUTING_TABLE.size());
561 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
562 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
563 assertEquals(1, BRIDGING_TABLE.size());
564 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
565 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan9f08b102017-08-09 16:50:15 -0700566
567 // Move the host to an invalid location
568 // Expect: Old flow is removed. New flow is not created
569 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700570 assertEquals(0, ROUTING_TABLE.size());
571 assertEquals(0, BRIDGING_TABLE.size());
Charles Chan9f08b102017-08-09 16:50:15 -0700572
573 // Move the host to a valid location
574 // Expect: add one new routing rule, one new bridging rule
575 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700576 assertEquals(1, ROUTING_TABLE.size());
577 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
578 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
579 assertEquals(1, BRIDGING_TABLE.size());
580 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
581 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan9f08b102017-08-09 16:50:15 -0700582 }
583
584 @Test
Charles Chanf82d1552018-07-23 15:27:34 -0700585 public void testDualHomedHostMoveToInvalidLocation() {
Charles Chan9f08b102017-08-09 16:50:15 -0700586 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
587 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
588 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
589 Sets.newHashSet(HOST_LOC11, HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
590 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
591 Sets.newHashSet(HOST_LOC61, HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
592
593 // Add a host
594 // Expect: add two new routing rules, two new bridging rules
595 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700596 assertEquals(2, ROUTING_TABLE.size());
597 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
598 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
599 assertEquals(2, BRIDGING_TABLE.size());
600 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
601 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan9f08b102017-08-09 16:50:15 -0700602
603 // Move first host location to an invalid location
604 // Expect: One routing and one bridging flow
605 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700606 assertEquals(1, ROUTING_TABLE.size());
607 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
608 assertEquals(1, BRIDGING_TABLE.size());
609 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan9f08b102017-08-09 16:50:15 -0700610
611 // Move second host location to an invalid location
612 // Expect: No routing or bridging rule
613 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700614 assertEquals(0, ROUTING_TABLE.size());
615 assertEquals(0, BRIDGING_TABLE.size());
Charles Chan9f08b102017-08-09 16:50:15 -0700616
617 // Move second host location back to a valid location
618 // Expect: One routing and one bridging flow
619 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host3));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700620 assertEquals(1, ROUTING_TABLE.size());
621 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
622 assertEquals(1, BRIDGING_TABLE.size());
623 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan9f08b102017-08-09 16:50:15 -0700624
625 // Move first host location back to a valid location
626 // Expect: Two routing and two bridging flow
627 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700628 assertEquals(2, ROUTING_TABLE.size());
629 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
630 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
631 assertEquals(2, BRIDGING_TABLE.size());
632 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
633 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan9f08b102017-08-09 16:50:15 -0700634 }
635
636 @Test
Charles Chanf82d1552018-07-23 15:27:34 -0700637 public void testDualHomingSingleLocationFail() {
Charles Chan65238242017-06-22 18:03:14 -0700638 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
639 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
640 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
641 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
642
643 // Add a host
644 // Expect: add four new routing rules, two new bridging rules
645 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700646 assertEquals(4, ROUTING_TABLE.size());
647 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
648 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
649 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
650 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
651 assertEquals(2, BRIDGING_TABLE.size());
652 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
653 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan65238242017-06-22 18:03:14 -0700654
655 // Host becomes single-homed
656 // Expect: redirect flows from host location to pair link
657 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700658 assertEquals(4, ROUTING_TABLE.size());
659 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
660 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
661 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
662 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
663 assertEquals(2, BRIDGING_TABLE.size());
664 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
665 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan65238242017-06-22 18:03:14 -0700666
667 // Host becomes dual-homed again
668 // Expect: Redirect flows from pair link back to host location
669 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700670 assertEquals(4, ROUTING_TABLE.size());
671 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
672 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
Charles Chan47933752017-11-30 15:37:50 -0800673 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
674 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
Charles Chan50bb6ef2018-04-18 18:41:05 -0700675 assertEquals(2, BRIDGING_TABLE.size());
676 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan1a3b02a2017-08-18 17:11:34 -0700677 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan65238242017-06-22 18:03:14 -0700678 }
679
680 @Test
Charles Chanf82d1552018-07-23 15:27:34 -0700681 public void testDualHomingBothLocationFail() {
Charles Chan65238242017-06-22 18:03:14 -0700682 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
683 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
684 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
685 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
686
687 // Add a host
688 // Expect: add four new routing rules, two new bridging rules
689 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700690 assertEquals(4, ROUTING_TABLE.size());
691 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
692 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
693 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
694 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
695 assertEquals(2, BRIDGING_TABLE.size());
696 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
697 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan65238242017-06-22 18:03:14 -0700698
699 // Host becomes single-homed
700 // Expect: redirect flows from host location to pair link
701 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700702 assertEquals(4, ROUTING_TABLE.size());
703 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
704 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
705 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
706 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
707 assertEquals(2, BRIDGING_TABLE.size());
708 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
709 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan65238242017-06-22 18:03:14 -0700710
711 // Host loses both locations
712 // Expect: Remove last location and all previous redirection flows
713 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, host2));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700714 assertEquals(0, ROUTING_TABLE.size());
715 assertEquals(0, BRIDGING_TABLE.size());
Charles Chan65238242017-06-22 18:03:14 -0700716 }
717
718 @Test
Charles Chanf82d1552018-07-23 15:27:34 -0700719 public void testHostUpdated() {
Charles Chan2e2e3402017-06-19 14:00:53 -0700720 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700721 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700722 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700723 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP21), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700724 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700725 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP12), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700726
727 // Add a host
Charles Chanf9a52702017-06-16 15:19:24 -0700728 // Expect: add one new routing rule. Add one new bridging rule.
Charles Chan2e2e3402017-06-19 14:00:53 -0700729 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700730 assertEquals(1, ROUTING_TABLE.size());
731 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
732 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
733 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
734 assertEquals(1, BRIDGING_TABLE.size());
735 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(HOST_LOC11.deviceId(), HOST_MAC,
736 INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700737
738 // Update the host IP to same subnet
739 // Expect: update routing rule with new IP. No change to bridging rule.
740 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700741 assertEquals(1, ROUTING_TABLE.size());
742 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
743 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
744 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
745 assertEquals(1, BRIDGING_TABLE.size());
746 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700747
748 // Update the host IP to different subnet
749 // Expect: Remove routing rule. No change to bridging rule.
750 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host3));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700751 assertEquals(0, ROUTING_TABLE.size());
752 assertEquals(1, BRIDGING_TABLE.size());
753 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700754 }
755
756 @Test
Charles Chanf82d1552018-07-23 15:27:34 -0700757 public void testDelayedIpAndLocation() {
Charles Chan3d650a62017-11-20 08:46:24 -0800758 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
759 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(), false);
760 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
761 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11), false);
762 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
763 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
764
765 // Add a dual-home host with only one location and no IP
766 // Expect: only bridging redirection works
767 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
768 assertEquals(0, ROUTING_TABLE.size());
769 assertEquals(2, BRIDGING_TABLE.size());
770 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
771 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
772
773 // Discover IP
774 // Expect: routing redirection should also work
Charles Chan47933752017-11-30 15:37:50 -0800775 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host1));
Charles Chan3d650a62017-11-20 08:46:24 -0800776 assertEquals(2, ROUTING_TABLE.size());
777 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
778 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
779 assertEquals(2, BRIDGING_TABLE.size());
780 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
781 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan47933752017-11-30 15:37:50 -0800782 // Expect probe to be sent out on pair device
Charles Chanff79dd92018-06-01 16:33:48 -0700783 assertTrue(mockLocationProbingService.verifyProbe(host2, CP41, ProbeMode.DISCOVER));
Charles Chan3d650a62017-11-20 08:46:24 -0800784
785 // Discover location
786 // Expect: cancel all redirections
Charles Chan47933752017-11-30 15:37:50 -0800787 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
Charles Chan3d650a62017-11-20 08:46:24 -0800788 assertEquals(2, ROUTING_TABLE.size());
789 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
Charles Chan50bb6ef2018-04-18 18:41:05 -0700790 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
Charles Chan3d650a62017-11-20 08:46:24 -0800791 assertEquals(2, BRIDGING_TABLE.size());
792 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan50bb6ef2018-04-18 18:41:05 -0700793 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan47933752017-11-30 15:37:50 -0800794 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
Charles Chan3d650a62017-11-20 08:46:24 -0800795 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
796 }
797
798 @Test
Charles Chanf82d1552018-07-23 15:27:34 -0700799 public void testDelayedIpAndLocation2() {
Charles Chan3d650a62017-11-20 08:46:24 -0800800 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
801 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(), false);
802 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
803 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(), false);
804 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
805 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
806
807 // Add a dual-home host with only one location and no IP
808 // Expect: only bridging redirection works
809 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
810 assertEquals(0, ROUTING_TABLE.size());
811 assertEquals(2, BRIDGING_TABLE.size());
812 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
813 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
814
815 // Discover Location
816 // Expect: cancel bridging redirections
817 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
818 assertEquals(0, ROUTING_TABLE.size());
819 assertEquals(2, BRIDGING_TABLE.size());
820 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
821 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
822
823 // Discover IP
824 // Expect: add IP rules to both location
825 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host2));
826 assertEquals(2, ROUTING_TABLE.size());
827 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
828 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
829 assertEquals(2, BRIDGING_TABLE.size());
830 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
831 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
832 }
833
834 @Test
Charles Chanf82d1552018-07-23 15:27:34 -0700835 public void testDualHomedHostUpdated() {
Charles Chanf9a52702017-06-16 15:19:24 -0700836 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
837 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
838 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
839 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP21), false);
840 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
841 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP13, HOST_IP14), false);
842
843 // Add a dual-homed host with two locations and two IPs
844 // Expect: add four new routing rules. Add two new bridging rules
845 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700846 assertEquals(4, ROUTING_TABLE.size());
847 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
848 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
849 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
850 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
851 assertEquals(2, BRIDGING_TABLE.size());
852 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
853 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700854
855 // Update both host IPs
856 // Expect: update routing rules with new IP. No change to bridging rule.
857 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700858 assertEquals(4, ROUTING_TABLE.size());
859 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
860 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
861 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())));
862 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP14.toIpPrefix())));
863 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
864 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
865 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())));
866 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP14.toIpPrefix())));
867 assertEquals(2, BRIDGING_TABLE.size());
868 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
869 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700870
871 // Update one of the host IP to different subnet
872 // Expect: update routing rule with new IP. No change to bridging rule.
873 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host3));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700874 assertEquals(2, ROUTING_TABLE.size());
875 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
876 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
877 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
878 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
879 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP21.toIpPrefix())));
880 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
881 assertEquals(2, BRIDGING_TABLE.size());
882 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
883 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700884 }
Charles Chanf76de302018-06-15 18:54:18 -0700885
886 @Test
887 public void testVlanForPairPort() {
888 assertEquals(INTF_VLAN_UNTAGGED, hostHandler.vlanForPairPort(VlanId.NONE, CP11));
889 assertEquals(INTF_VLAN_NATIVE, hostHandler.vlanForPairPort(VlanId.NONE, CP13));
890 assertEquals(INTF_VLAN_TAGGED_1, hostHandler.vlanForPairPort(INTF_VLAN_TAGGED_1, CP13));
891 assertNull(hostHandler.vlanForPairPort(INTF_VLAN_UNTAGGED, CP11));
892 assertNull(hostHandler.vlanForPairPort(INTF_VLAN_UNTAGGED, CP13));
893 assertNull(hostHandler.vlanForPairPort(VlanId.NONE, CP51));
894 assertNull(hostHandler.vlanForPairPort(INTF_VLAN_UNTAGGED, CP51));
895 }
Charles Chan4d639392018-06-21 19:07:12 -0700896
897 @Test
Charles Chanf82d1552018-07-23 15:27:34 -0700898 public void testHostRemovedWithRouteRemoved() {
Charles Chan4d639392018-06-21 19:07:12 -0700899 Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
900 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
901
902 // Add a host
903 // Expect: add one routing rule and one bridging rule
904 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
905 assertEquals(1, ROUTING_TABLE.size());
906 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
907 assertEquals(1, BRIDGING_TABLE.size());
908 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
909
910 IpPrefix prefix = IpPrefix.valueOf("55.55.55.0/24");
911
912 // Setting up mock route service
913 RouteService routeService = hostHandler.srManager.routeService;
914 reset(routeService);
915
916 IpAddress nextHopIp2 = IpAddress.valueOf("20.0.0.1");
917 MacAddress nextHopMac2 = MacAddress.valueOf("00:22:33:44:55:66");
918 VlanId nextHopVlan2 = VlanId.NONE;
919
920 Route r1 = new Route(Route.Source.STATIC, prefix, HOST_IP11);
921 ResolvedRoute rr1 = new ResolvedRoute(r1, HOST_MAC, VlanId.NONE);
922 Route r2 = new Route(Route.Source.STATIC, prefix, nextHopIp2);
923 ResolvedRoute rr2 = new ResolvedRoute(r2, nextHopMac2, nextHopVlan2);
924 RouteInfo routeInfo = new RouteInfo(prefix, rr1, Sets.newHashSet(rr1, rr2));
925 RouteTableId routeTableId = new RouteTableId("ipv4");
926
927 expect(routeService.getRouteTables()).andReturn(Sets.newHashSet(routeTableId));
928 expect(routeService.getRoutes(routeTableId)).andReturn(Sets.newHashSet(routeInfo));
929 replay(routeService);
930
931 // Setting up mock device configuration
932 hostHandler.srManager.deviceConfiguration = EasyMock.createNiceMock(DeviceConfiguration.class);
933 DeviceConfiguration deviceConfiguration = hostHandler.srManager.deviceConfiguration;
934 expect(deviceConfiguration.inSameSubnet(CP11, HOST_IP11)).andReturn(true);
935 deviceConfiguration.removeSubnet(CP11, prefix);
936 expectLastCall();
937 replay(deviceConfiguration);
938
939 // Remove the host
940 // Expect: add the routing rule and the bridging rule
941 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, subject));
942 assertEquals(0, ROUTING_TABLE.size());
943 assertEquals(0, BRIDGING_TABLE.size());
944
945 // Expect: subnet is removed from device config
946 verify(deviceConfiguration);
947 }
Charles Chanf82d1552018-07-23 15:27:34 -0700948
949 @Test
950 public void testHostProbing() {
951 // Case: [1A/1, 1B/1] -> [1A/2, 1B/1]
952 // Expect: DISCOVER probe should be sent to every port on 1B that has the same VLAN as 1A/2
953 // VERIFY probe should be sent to 1B/1
954 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
955 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
956 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
957 Sets.newHashSet(HOST_LOC32, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
958 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
959
960 hostHandler.srManager.probingService = createMock(HostProbingService.class);
961 hostHandler.srManager.probingService.probeHost(host2, CP41, ProbeMode.DISCOVER);
962 expectLastCall();
963 hostHandler.srManager.probingService.probeHost(host2, CP42, ProbeMode.DISCOVER);
964 expectLastCall();
965 hostHandler.srManager.probingService.probeHost(host2, CP41, ProbeMode.VERIFY);
966 expectLastCall();
967 replay(hostHandler.srManager.probingService);
968
969 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
970
971 verify(hostHandler.srManager.probingService);
972 }
Ray Milkeyfacf2862017-08-03 11:58:29 -0700973}