blob: d97cbc71d894a7ad7ca814bea88db3d0695928e0 [file] [log] [blame]
Charles Chan114aec72017-06-19 14:00:53 -07001/*
Brian O'Connor0947d7e2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Charles Chan114aec72017-06-19 14:00:53 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.segmentrouting;
18
Charles Chan3ed34d82017-06-22 18:03:14 -070019import com.fasterxml.jackson.databind.JsonNode;
20import com.fasterxml.jackson.databind.ObjectMapper;
Charles Chan114aec72017-06-19 14:00:53 -070021import com.google.common.collect.Lists;
22import com.google.common.collect.Maps;
23import com.google.common.collect.Sets;
Charles Chanbd84dd52018-06-21 19:07:12 -070024import org.easymock.EasyMock;
Charles Chan114aec72017-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;
piercf557922019-05-17 20:47:06 +020031import org.onlab.util.PredictableExecutor;
Charles Chan6c624992017-08-18 17:11:34 -070032import org.onosproject.net.config.ConfigApplyDelegate;
Charles Chan6e90fbb2018-07-23 15:27:34 -070033import org.onosproject.net.host.HostProbingService;
Charles Chanc6bcdf92018-06-01 16:33:48 -070034import org.onosproject.net.host.ProbeMode;
Ray Milkeyc2d43be2017-08-03 11:58:29 -070035import org.onosproject.net.intf.Interface;
Charles Chan114aec72017-06-19 14:00:53 -070036import org.onosproject.net.ConnectPoint;
37import org.onosproject.net.DefaultHost;
38import org.onosproject.net.DeviceId;
39import org.onosproject.net.Host;
40import org.onosproject.net.HostId;
41import org.onosproject.net.HostLocation;
42import org.onosproject.net.PortNumber;
43import org.onosproject.net.config.NetworkConfigRegistryAdapter;
Charles Chan114aec72017-06-19 14:00:53 -070044import org.onosproject.net.flow.TrafficTreatment;
Charles Chan114aec72017-06-19 14:00:53 -070045import org.onosproject.net.host.HostEvent;
46import org.onosproject.net.host.InterfaceIpAddress;
47import org.onosproject.net.provider.ProviderId;
Charles Chanbd84dd52018-06-21 19:07:12 -070048import org.onosproject.routeservice.ResolvedRoute;
49import org.onosproject.routeservice.Route;
50import org.onosproject.routeservice.RouteInfo;
51import org.onosproject.routeservice.RouteService;
52import org.onosproject.routeservice.RouteTableId;
Charles Chan114aec72017-06-19 14:00:53 -070053import org.onosproject.segmentrouting.config.DeviceConfiguration;
Charles Chan3ed34d82017-06-22 18:03:14 -070054import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
Charles Chand66d6712018-03-29 16:03:41 -070055import org.onosproject.store.service.StorageService;
56import org.onosproject.store.service.TestConsistentMap;
Charles Chan114aec72017-06-19 14:00:53 -070057
58import java.util.Map;
Charles Chan114aec72017-06-19 14:00:53 -070059import java.util.Set;
Charles Chan114aec72017-06-19 14:00:53 -070060
Charles Chand66d6712018-03-29 16:03:41 -070061import static org.easymock.EasyMock.createMock;
Charles Chanbd84dd52018-06-21 19:07:12 -070062import static org.easymock.EasyMock.createNiceMock;
Charles Chand66d6712018-03-29 16:03:41 -070063import static org.easymock.EasyMock.expect;
Charles Chanbd84dd52018-06-21 19:07:12 -070064import static org.easymock.EasyMock.expectLastCall;
Charles Chand66d6712018-03-29 16:03:41 -070065import static org.easymock.EasyMock.replay;
Charles Chanbd84dd52018-06-21 19:07:12 -070066import static org.easymock.EasyMock.reset;
67import static org.easymock.EasyMock.verify;
Charles Chan114aec72017-06-19 14:00:53 -070068import static org.junit.Assert.*;
piercf557922019-05-17 20:47:06 +020069import static org.onlab.util.Tools.groupedThreads;
Charles Chan114aec72017-06-19 14:00:53 -070070
piercf557922019-05-17 20:47:06 +020071/**
Charles Chan114aec72017-06-19 14:00:53 -070072 * Unit test for {@link HostHandler}.
73 */
74public class HostHandlerTest {
Charles Chan114aec72017-06-19 14:00:53 -070075 private HostHandler hostHandler;
76
77 // Mocked routing and bridging tables
Charles Chan6c624992017-08-18 17:11:34 -070078 private static final Map<MockBridgingTableKey, MockBridgingTableValue> BRIDGING_TABLE =
79 Maps.newConcurrentMap();
80 private static final Map<MockRoutingTableKey, MockRoutingTableValue> ROUTING_TABLE =
81 Maps.newConcurrentMap();
Charles Chan910be6a2017-08-23 14:46:43 -070082 private static final Map<ConnectPoint, Set<IpPrefix>> SUBNET_TABLE = Maps.newConcurrentMap();
Charles Chan114aec72017-06-19 14:00:53 -070083 // Mocked Next Id
Charles Chan6c624992017-08-18 17:11:34 -070084 private static final Map<Integer, TrafficTreatment> NEXT_TABLE = Maps.newConcurrentMap();
Charles Chan114aec72017-06-19 14:00:53 -070085
Charles Chand9265a32017-06-16 15:19:24 -070086 // Host Mac, VLAN
Charles Chan114aec72017-06-19 14:00:53 -070087 private static final ProviderId PROVIDER_ID = ProviderId.NONE;
88 private static final MacAddress HOST_MAC = MacAddress.valueOf("00:00:00:00:00:01");
89 private static final VlanId HOST_VLAN_UNTAGGED = VlanId.NONE;
90 private static final HostId HOST_ID_UNTAGGED = HostId.hostId(HOST_MAC, HOST_VLAN_UNTAGGED);
91 private static final VlanId HOST_VLAN_TAGGED = VlanId.vlanId((short) 20);
92 private static final HostId HOST_ID_TAGGED = HostId.hostId(HOST_MAC, HOST_VLAN_TAGGED);
Charles Chand9265a32017-06-16 15:19:24 -070093 // Host IP
94 private static final IpAddress HOST_IP11 = IpAddress.valueOf("10.0.1.1");
95 private static final IpAddress HOST_IP21 = IpAddress.valueOf("10.0.2.1");
96 private static final IpAddress HOST_IP12 = IpAddress.valueOf("10.0.1.2");
97 private static final IpAddress HOST_IP13 = IpAddress.valueOf("10.0.1.3");
98 private static final IpAddress HOST_IP14 = IpAddress.valueOf("10.0.1.4");
Charles Chan6e90fbb2018-07-23 15:27:34 -070099 private static final IpAddress HOST_IP33 = IpAddress.valueOf("10.0.3.3");
Charles Chand9265a32017-06-16 15:19:24 -0700100 // Device
101 private static final DeviceId DEV1 = DeviceId.deviceId("of:0000000000000001");
102 private static final DeviceId DEV2 = DeviceId.deviceId("of:0000000000000002");
Charles Chanabfe7e02017-08-09 16:50:15 -0700103 private static final DeviceId DEV3 = DeviceId.deviceId("of:0000000000000003");
104 private static final DeviceId DEV4 = DeviceId.deviceId("of:0000000000000004");
105 private static final DeviceId DEV5 = DeviceId.deviceId("of:0000000000000005");
106 private static final DeviceId DEV6 = DeviceId.deviceId("of:0000000000000006");
Charles Chand9265a32017-06-16 15:19:24 -0700107 // Port
108 private static final PortNumber P1 = PortNumber.portNumber(1);
109 private static final PortNumber P2 = PortNumber.portNumber(2);
110 private static final PortNumber P3 = PortNumber.portNumber(3);
Charles Chan3ed34d82017-06-22 18:03:14 -0700111 private static final PortNumber P9 = PortNumber.portNumber(9);
Charles Chand9265a32017-06-16 15:19:24 -0700112 // Connect Point
113 private static final ConnectPoint CP11 = new ConnectPoint(DEV1, P1);
114 private static final HostLocation HOST_LOC11 = new HostLocation(CP11, 0);
115 private static final ConnectPoint CP12 = new ConnectPoint(DEV1, P2);
116 private static final HostLocation HOST_LOC12 = new HostLocation(CP12, 0);
117 private static final ConnectPoint CP13 = new ConnectPoint(DEV1, P3);
118 private static final HostLocation HOST_LOC13 = new HostLocation(CP13, 0);
119 private static final ConnectPoint CP21 = new ConnectPoint(DEV2, P1);
120 private static final HostLocation HOST_LOC21 = new HostLocation(CP21, 0);
121 private static final ConnectPoint CP22 = new ConnectPoint(DEV2, P2);
122 private static final HostLocation HOST_LOC22 = new HostLocation(CP22, 0);
Charles Chan3ed34d82017-06-22 18:03:14 -0700123 // Connect Point for dual-homed host failover
124 private static final ConnectPoint CP31 = new ConnectPoint(DEV3, P1);
125 private static final HostLocation HOST_LOC31 = new HostLocation(CP31, 0);
Charles Chanceb2a2e2017-09-12 18:57:47 -0700126 private static final ConnectPoint CP32 = new ConnectPoint(DEV3, P2);
127 private static final HostLocation HOST_LOC32 = new HostLocation(CP32, 0);
Charles Chan6e90fbb2018-07-23 15:27:34 -0700128 private static final ConnectPoint CP33 = new ConnectPoint(DEV3, P3);
129 private static final HostLocation HOST_LOC33 = new HostLocation(CP33, 0);
Charles Chan3ed34d82017-06-22 18:03:14 -0700130 private static final ConnectPoint CP41 = new ConnectPoint(DEV4, P1);
131 private static final HostLocation HOST_LOC41 = new HostLocation(CP41, 0);
Charles Chan6e90fbb2018-07-23 15:27:34 -0700132 private static final ConnectPoint CP42 = new ConnectPoint(DEV4, P2);
133 private static final HostLocation HOST_LOC42 = new HostLocation(CP42, 0);
Charles Chan3ed34d82017-06-22 18:03:14 -0700134 private static final ConnectPoint CP39 = new ConnectPoint(DEV3, P9);
135 private static final ConnectPoint CP49 = new ConnectPoint(DEV4, P9);
Charles Chanabfe7e02017-08-09 16:50:15 -0700136 // Conenct Point for mastership test
137 private static final ConnectPoint CP51 = new ConnectPoint(DEV5, P1);
138 private static final HostLocation HOST_LOC51 = new HostLocation(CP51, 0);
139 private static final ConnectPoint CP61 = new ConnectPoint(DEV6, P1);
140 private static final HostLocation HOST_LOC61 = new HostLocation(CP61, 0);
Charles Chand9265a32017-06-16 15:19:24 -0700141 // Interface VLAN
Charles Chan114aec72017-06-19 14:00:53 -0700142 private static final VlanId INTF_VLAN_UNTAGGED = VlanId.vlanId((short) 10);
Charles Chan868c9572018-06-15 18:54:18 -0700143 private static final VlanId INTF_VLAN_TAGGED_1 = VlanId.vlanId((short) 20);
144 private static final Set<VlanId> INTF_VLAN_TAGGED = Sets.newHashSet(INTF_VLAN_TAGGED_1);
Charles Chan114aec72017-06-19 14:00:53 -0700145 private static final VlanId INTF_VLAN_NATIVE = VlanId.vlanId((short) 30);
Charles Chan3ed34d82017-06-22 18:03:14 -0700146 private static final Set<VlanId> INTF_VLAN_PAIR = Sets.newHashSet(VlanId.vlanId((short) 10),
147 VlanId.vlanId((short) 20), VlanId.vlanId((short) 30));
Charles Chanceb2a2e2017-09-12 18:57:47 -0700148 private static final VlanId INTF_VLAN_OTHER = VlanId.vlanId((short) 40);
Charles Chand9265a32017-06-16 15:19:24 -0700149 // Interface subnet
150 private static final IpPrefix INTF_PREFIX1 = IpPrefix.valueOf("10.0.1.254/24");
151 private static final IpPrefix INTF_PREFIX2 = IpPrefix.valueOf("10.0.2.254/24");
Charles Chanceb2a2e2017-09-12 18:57:47 -0700152 private static final IpPrefix INTF_PREFIX3 = IpPrefix.valueOf("10.0.3.254/24");
Charles Chand9265a32017-06-16 15:19:24 -0700153 private static final InterfaceIpAddress INTF_IP1 =
154 new InterfaceIpAddress(INTF_PREFIX1.address(), INTF_PREFIX1);
155 private static final InterfaceIpAddress INTF_IP2 =
156 new InterfaceIpAddress(INTF_PREFIX2.address(), INTF_PREFIX2);
Charles Chanceb2a2e2017-09-12 18:57:47 -0700157 private static final InterfaceIpAddress INTF_IP3 =
158 new InterfaceIpAddress(INTF_PREFIX3.address(), INTF_PREFIX3);
Charles Chan6c624992017-08-18 17:11:34 -0700159 // Interfaces
160 private static final Interface INTF11 =
161 new Interface(null, CP11, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
162 INTF_VLAN_UNTAGGED, null, null);
163 private static final Interface INTF12 =
164 new Interface(null, CP12, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
165 INTF_VLAN_UNTAGGED, null, null);
166 private static final Interface INTF13 =
167 new Interface(null, CP13, Lists.newArrayList(INTF_IP2), MacAddress.NONE, null,
168 null, INTF_VLAN_TAGGED, INTF_VLAN_NATIVE);
169 private static final Interface INTF21 =
170 new Interface(null, CP21, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
171 INTF_VLAN_UNTAGGED, null, null);
172 private static final Interface INTF22 =
173 new Interface(null, CP22, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
174 INTF_VLAN_UNTAGGED, null, null);
175 private static final Interface INTF31 =
176 new Interface(null, CP31, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
177 INTF_VLAN_UNTAGGED, null, null);
Charles Chanceb2a2e2017-09-12 18:57:47 -0700178 private static final Interface INTF32 =
Charles Chan6e90fbb2018-07-23 15:27:34 -0700179 new Interface(null, CP32, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
180 INTF_VLAN_UNTAGGED, null, null);
181 private static final Interface INTF33 =
182 new Interface(null, CP33, Lists.newArrayList(INTF_IP3), MacAddress.NONE, null,
Charles Chanceb2a2e2017-09-12 18:57:47 -0700183 INTF_VLAN_OTHER, null, null);
Charles Chan6c624992017-08-18 17:11:34 -0700184 private static final Interface INTF39 =
185 new Interface(null, CP39, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
186 null, INTF_VLAN_PAIR, null);
187 private static final Interface INTF41 =
188 new Interface(null, CP41, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
189 INTF_VLAN_UNTAGGED, null, null);
Charles Chan6e90fbb2018-07-23 15:27:34 -0700190 private static final Interface INTF42 =
191 new Interface(null, CP42, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
192 INTF_VLAN_UNTAGGED, null, null);
Charles Chan6c624992017-08-18 17:11:34 -0700193 private static final Interface INTF49 =
194 new Interface(null, CP49, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
195 null, INTF_VLAN_PAIR, null);
Charles Chand9265a32017-06-16 15:19:24 -0700196 // Host
197 private static final Host HOST1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC,
198 HOST_VLAN_UNTAGGED, Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11),
199 false);
Charles Chan114aec72017-06-19 14:00:53 -0700200
Charles Chan6c624992017-08-18 17:11:34 -0700201 // A set of hosts
202 private static final Set<Host> HOSTS = Sets.newHashSet(HOST1);
203 // A set of devices of which we have mastership
204 private static final Set<DeviceId> LOCAL_DEVICES = Sets.newHashSet(DEV1, DEV2, DEV3, DEV4);
205 // A set of interfaces
206 private static final Set<Interface> INTERFACES = Sets.newHashSet(INTF11, INTF12, INTF13, INTF21,
Charles Chan6e90fbb2018-07-23 15:27:34 -0700207 INTF22, INTF31, INTF32, INTF33, INTF39, INTF41, INTF42, INTF49);
Charles Chan6c624992017-08-18 17:11:34 -0700208
Charles Chanc6bcdf92018-06-01 16:33:48 -0700209 private MockHostProbingService mockLocationProbingService;
Charles Chan873661e2017-11-30 15:37:50 -0800210
Charles Chan114aec72017-06-19 14:00:53 -0700211 @Before
Charles Chan6e90fbb2018-07-23 15:27:34 -0700212 public void setUp() {
Charles Chan6c624992017-08-18 17:11:34 -0700213 // Initialize pairDevice and pairLocalPort config
214 ObjectMapper mapper = new ObjectMapper();
215 ConfigApplyDelegate delegate = config -> { };
216
217 SegmentRoutingDeviceConfig dev3Config = new SegmentRoutingDeviceConfig();
218 JsonNode dev3Tree = mapper.createObjectNode();
219 dev3Config.init(DEV3, "host-handler-test", dev3Tree, mapper, delegate);
220 dev3Config.setPairDeviceId(DEV4).setPairLocalPort(P9);
221
222 SegmentRoutingDeviceConfig dev4Config = new SegmentRoutingDeviceConfig();
223 JsonNode dev4Tree = mapper.createObjectNode();
224 dev4Config.init(DEV4, "host-handler-test", dev4Tree, mapper, delegate);
225 dev4Config.setPairDeviceId(DEV3).setPairLocalPort(P9);
226
227 MockNetworkConfigRegistry mockNetworkConfigRegistry = new MockNetworkConfigRegistry();
228 mockNetworkConfigRegistry.applyConfig(dev3Config);
229 mockNetworkConfigRegistry.applyConfig(dev4Config);
230
231 // Initialize Segment Routing Manager
232 SegmentRoutingManager srManager = new MockSegmentRoutingManager(NEXT_TABLE);
Charles Chand66d6712018-03-29 16:03:41 -0700233 srManager.storageService = createMock(StorageService.class);
234 expect(srManager.storageService.consistentMapBuilder()).andReturn(new TestConsistentMap.Builder<>()).anyTimes();
235 replay(srManager.storageService);
Charles Chan114aec72017-06-19 14:00:53 -0700236 srManager.cfgService = new NetworkConfigRegistryAdapter();
237 srManager.deviceConfiguration = new DeviceConfiguration(srManager);
Charles Chan6c624992017-08-18 17:11:34 -0700238 srManager.flowObjectiveService = new MockFlowObjectiveService(BRIDGING_TABLE, NEXT_TABLE);
239 srManager.routingRulePopulator = new MockRoutingRulePopulator(srManager, ROUTING_TABLE);
Charles Chanc4d68882018-03-15 16:41:10 -0700240 srManager.defaultRoutingHandler = new MockDefaultRoutingHandler(srManager, SUBNET_TABLE, ROUTING_TABLE);
Charles Chan6c624992017-08-18 17:11:34 -0700241 srManager.interfaceService = new MockInterfaceService(INTERFACES);
242 srManager.mastershipService = new MockMastershipService(LOCAL_DEVICES);
243 srManager.hostService = new MockHostService(HOSTS);
244 srManager.cfgService = mockNetworkConfigRegistry;
Charles Chanc6bcdf92018-06-01 16:33:48 -0700245 mockLocationProbingService = new MockHostProbingService();
Charles Chan873661e2017-11-30 15:37:50 -0800246 srManager.probingService = mockLocationProbingService;
Saurav Dase6c448a2018-01-18 12:07:33 -0800247 srManager.linkHandler = new MockLinkHandler(srManager);
Charles Chan114aec72017-06-19 14:00:53 -0700248
Charles Chanbd84dd52018-06-21 19:07:12 -0700249 // Not important for most of the HostHandler test case. Simply return an empty set here
250 srManager.routeService = createNiceMock(RouteService.class);
251 expect(srManager.routeService.getRouteTables()).andReturn(Sets.newHashSet()).anyTimes();
252 replay(srManager.routeService);
253
Charles Chan114aec72017-06-19 14:00:53 -0700254 hostHandler = new HostHandler(srManager);
piercf557922019-05-17 20:47:06 +0200255 hostHandler.hostWorkers = new PredictableExecutor(
256 0, groupedThreads("onos/sr", "h-worker-%d"), true);
Charles Chan114aec72017-06-19 14:00:53 -0700257
Charles Chan6c624992017-08-18 17:11:34 -0700258 ROUTING_TABLE.clear();
259 BRIDGING_TABLE.clear();
Charles Chan114aec72017-06-19 14:00:53 -0700260 }
261
262 @Test
Charles Chan6e90fbb2018-07-23 15:27:34 -0700263 public void init() {
Charles Chand9265a32017-06-16 15:19:24 -0700264 hostHandler.init(DEV1);
Charles Chan6c624992017-08-18 17:11:34 -0700265 assertEquals(1, ROUTING_TABLE.size());
266 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
267 assertEquals(1, BRIDGING_TABLE.size());
268 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chand9265a32017-06-16 15:19:24 -0700269
270 hostHandler.init(DEV2);
Charles Chan6c624992017-08-18 17:11:34 -0700271 assertEquals(2, ROUTING_TABLE.size());
272 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
273 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
274 assertEquals(2, BRIDGING_TABLE.size());
275 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
276 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chand9265a32017-06-16 15:19:24 -0700277 }
278
279 @Test(expected = IllegalArgumentException.class)
Charles Chan6e90fbb2018-07-23 15:27:34 -0700280 public void testHostAddedAtWrongLocation() {
Charles Chand9265a32017-06-16 15:19:24 -0700281 hostHandler.processHostAddedAtLocation(HOST1, HOST_LOC13);
282 }
283
284
285 @Test()
Charles Chan6e90fbb2018-07-23 15:27:34 -0700286 public void testHostAddedAtCorrectLocation() {
Charles Chand9265a32017-06-16 15:19:24 -0700287 hostHandler.processHostAddedAtLocation(HOST1, HOST_LOC11);
Charles Chan6c624992017-08-18 17:11:34 -0700288 assertEquals(1, ROUTING_TABLE.size());
289 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
290 assertEquals(1, BRIDGING_TABLE.size());
291 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan114aec72017-06-19 14:00:53 -0700292 }
293
294 @Test
Charles Chan6e90fbb2018-07-23 15:27:34 -0700295 public void testHostAdded() {
Charles Chan114aec72017-06-19 14:00:53 -0700296 Host subject;
297
298 // Untagged host discovered on untagged port
299 // Expect: add one routing rule and one bridging rule
300 subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700301 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan114aec72017-06-19 14:00:53 -0700302 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan6c624992017-08-18 17:11:34 -0700303 assertEquals(1, ROUTING_TABLE.size());
304 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
305 assertEquals(1, BRIDGING_TABLE.size());
306 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan114aec72017-06-19 14:00:53 -0700307
308 // Untagged host discovered on tagged/native port
309 // Expect: add one routing rule and one bridging rule
310 subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700311 Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP21), false);
Charles Chan114aec72017-06-19 14:00:53 -0700312 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan6c624992017-08-18 17:11:34 -0700313 assertEquals(2, ROUTING_TABLE.size());
314 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
315 assertEquals(2, BRIDGING_TABLE.size());
316 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_NATIVE)));
Charles Chan114aec72017-06-19 14:00:53 -0700317
318 // Tagged host discovered on untagged port
319 // Expect: ignore the host. No rule is added.
320 subject = new DefaultHost(PROVIDER_ID, HOST_ID_TAGGED, HOST_MAC, HOST_VLAN_TAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700321 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan114aec72017-06-19 14:00:53 -0700322 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan6c624992017-08-18 17:11:34 -0700323 assertEquals(2, ROUTING_TABLE.size());
324 assertEquals(2, BRIDGING_TABLE.size());
Charles Chan114aec72017-06-19 14:00:53 -0700325
326 // Tagged host discovered on tagged port with the same IP
327 // Expect: update existing route, add one bridging rule
328 subject = new DefaultHost(PROVIDER_ID, HOST_ID_TAGGED, HOST_MAC, HOST_VLAN_TAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700329 Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP21), false);
Charles Chan114aec72017-06-19 14:00:53 -0700330 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan6c624992017-08-18 17:11:34 -0700331 assertEquals(2, ROUTING_TABLE.size());
332 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
333 assertEquals(HOST_VLAN_TAGGED, ROUTING_TABLE.get(new MockRoutingTableKey(HOST_LOC13.deviceId(),
Charles Chand9265a32017-06-16 15:19:24 -0700334 HOST_IP21.toIpPrefix())).vlanId);
Charles Chan6c624992017-08-18 17:11:34 -0700335 assertEquals(3, BRIDGING_TABLE.size());
336 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, HOST_VLAN_TAGGED)));
Charles Chand9265a32017-06-16 15:19:24 -0700337 }
338
339 @Test
Charles Chan6e90fbb2018-07-23 15:27:34 -0700340 public void testDualHomedHostAdded() {
Charles Chand9265a32017-06-16 15:19:24 -0700341 // Add a dual-homed host that has 2 locations
342 // Expect: add two routing rules and two bridging rules
343 Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
344 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
345 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan6c624992017-08-18 17:11:34 -0700346 assertEquals(2, ROUTING_TABLE.size());
347 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
348 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
349 assertEquals(2, BRIDGING_TABLE.size());
350 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
351 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan114aec72017-06-19 14:00:53 -0700352 }
353
354 @Test
Charles Chan6e90fbb2018-07-23 15:27:34 -0700355 public void testSingleHomedHostAddedOnPairLeaf() {
Charles Chanceb2a2e2017-09-12 18:57:47 -0700356 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chan6e90fbb2018-07-23 15:27:34 -0700357 Sets.newHashSet(HOST_LOC33), Sets.newHashSet(HOST_IP33), false);
Charles Chanceb2a2e2017-09-12 18:57:47 -0700358
359 // Add a single-homed host with one location
360 // Expect: the pair link should not be utilized
361 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
362 assertEquals(1, ROUTING_TABLE.size());
Charles Chan6e90fbb2018-07-23 15:27:34 -0700363 assertEquals(P3, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP33.toIpPrefix())).portNumber);
Charles Chanceb2a2e2017-09-12 18:57:47 -0700364 assertEquals(1, BRIDGING_TABLE.size());
Charles Chan6e90fbb2018-07-23 15:27:34 -0700365 assertEquals(P3, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_OTHER)).portNumber);
Charles Chanceb2a2e2017-09-12 18:57:47 -0700366 }
367
368 @Test
Charles Chan6e90fbb2018-07-23 15:27:34 -0700369 public void testDualHomedHostAddedOneByOne() {
Charles Chanceb2a2e2017-09-12 18:57:47 -0700370 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
371 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11), false);
372 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
373 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
374
375 // Add a dual-homed host with one location
376 // Expect: the pair link is utilized temporarily before the second location is discovered
377 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
378 assertEquals(2, ROUTING_TABLE.size());
379 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
380 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
381 assertEquals(2, BRIDGING_TABLE.size());
382 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
383 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan873661e2017-11-30 15:37:50 -0800384 // Expect probe to be sent out on pair device
Charles Chanc6bcdf92018-06-01 16:33:48 -0700385 assertTrue(mockLocationProbingService.verifyProbe(host1, CP41, ProbeMode.DISCOVER));
Charles Chanceb2a2e2017-09-12 18:57:47 -0700386
387 // Add the second location of dual-homed host
388 // Expect: no longer use the pair link
389 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
390 assertEquals(2, ROUTING_TABLE.size());
391 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
Charles Chanfbcb8812018-04-18 18:41:05 -0700392 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
Charles Chanceb2a2e2017-09-12 18:57:47 -0700393 assertEquals(2, BRIDGING_TABLE.size());
394 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
395 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
396 }
397
398 @Test
Charles Chan6e90fbb2018-07-23 15:27:34 -0700399 public void testHostRemoved() {
Charles Chan114aec72017-06-19 14:00:53 -0700400 Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700401 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan114aec72017-06-19 14:00:53 -0700402
403 // Add a host
404 // Expect: add one routing rule and one bridging rule
405 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan6c624992017-08-18 17:11:34 -0700406 assertEquals(1, ROUTING_TABLE.size());
407 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
408 assertEquals(1, BRIDGING_TABLE.size());
409 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan114aec72017-06-19 14:00:53 -0700410
411 // Remove the host
412 // Expect: add the routing rule and the bridging rule
Charles Chand9265a32017-06-16 15:19:24 -0700413 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, subject));
Charles Chan6c624992017-08-18 17:11:34 -0700414 assertEquals(0, ROUTING_TABLE.size());
415 assertEquals(0, BRIDGING_TABLE.size());
Charles Chand9265a32017-06-16 15:19:24 -0700416 }
417
418 @Test
Charles Chan6e90fbb2018-07-23 15:27:34 -0700419 public void testDualHomedHostRemoved() {
Charles Chand9265a32017-06-16 15:19:24 -0700420 // Add a dual-homed host that has 2 locations
421 // Expect: add two routing rules and two bridging rules
422 Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
423 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
424 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan6c624992017-08-18 17:11:34 -0700425 assertEquals(2, ROUTING_TABLE.size());
426 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
427 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
428 assertEquals(2, BRIDGING_TABLE.size());
429 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
430 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chand9265a32017-06-16 15:19:24 -0700431
432 // Remove a dual-homed host that has 2 locations
433 // Expect: all routing and bridging rules are removed
434 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, subject));
Charles Chan6c624992017-08-18 17:11:34 -0700435 assertEquals(0, ROUTING_TABLE.size());
436 assertEquals(0, BRIDGING_TABLE.size());
Charles Chan114aec72017-06-19 14:00:53 -0700437 }
438
439 @Test
Charles Chan6e90fbb2018-07-23 15:27:34 -0700440 public void testHostMoved() {
Charles Chan114aec72017-06-19 14:00:53 -0700441 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700442 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan114aec72017-06-19 14:00:53 -0700443 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700444 Sets.newHashSet(HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
Charles Chan114aec72017-06-19 14:00:53 -0700445 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700446 Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP11), false);
Charles Chan114aec72017-06-19 14:00:53 -0700447
448 // Add a host
Charles Chan3ed34d82017-06-22 18:03:14 -0700449 // Expect: add one new routing rule, one new bridging rule
Charles Chan114aec72017-06-19 14:00:53 -0700450 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700451 assertEquals(1, ROUTING_TABLE.size());
452 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
453 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
454 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())));
455 assertEquals(1, BRIDGING_TABLE.size());
456 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
457 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan114aec72017-06-19 14:00:53 -0700458
Charles Chand9265a32017-06-16 15:19:24 -0700459 // Move the host to CP13, which has different subnet setting
Charles Chan114aec72017-06-19 14:00:53 -0700460 // Expect: remove routing rule. Change vlan in bridging rule.
Charles Chand9265a32017-06-16 15:19:24 -0700461 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700462 assertEquals(0, ROUTING_TABLE.size());
463 assertEquals(1, BRIDGING_TABLE.size());
464 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_NATIVE)));
465 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan114aec72017-06-19 14:00:53 -0700466
Charles Chand9265a32017-06-16 15:19:24 -0700467 // Move the host to CP21, which has same subnet setting
Charles Chan114aec72017-06-19 14:00:53 -0700468 // Expect: add a new routing rule. Change vlan in bridging rule.
Charles Chand9265a32017-06-16 15:19:24 -0700469 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host3));
Charles Chan6c624992017-08-18 17:11:34 -0700470 assertEquals(1, ROUTING_TABLE.size());
471 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
472 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
473 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
474 assertEquals(1, BRIDGING_TABLE.size());
475 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
476 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chand9265a32017-06-16 15:19:24 -0700477 }
478
479 @Test
Charles Chan6e90fbb2018-07-23 15:27:34 -0700480 public void testDualHomedHostMoved() {
Charles Chand9265a32017-06-16 15:19:24 -0700481 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
482 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
483 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
484 Sets.newHashSet(HOST_LOC12, HOST_LOC22), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
485 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
486 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP13, HOST_IP14), false);
487 Host host4 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
488 Sets.newHashSet(HOST_LOC11, HOST_LOC22), Sets.newHashSet(HOST_IP12, HOST_IP13), false);
Charles Chan4b5769a2018-04-25 18:51:46 -0400489 Host host5 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
490 Sets.newHashSet(HOST_LOC12, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
491
Charles Chand9265a32017-06-16 15:19:24 -0700492
493 // Add a host with IP11, IP12 and LOC11, LOC21
494 // Expect: 4 routing rules and 2 bridging rules
495 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700496 assertEquals(4, ROUTING_TABLE.size());
497 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
498 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
499 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
500 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
501 assertEquals(2, BRIDGING_TABLE.size());
502 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
503 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chand9265a32017-06-16 15:19:24 -0700504
Charles Chan4b5769a2018-04-25 18:51:46 -0400505 // Move the host to LOC12, LOC21 and keep the IP
506 // Expect: 4 routing rules and 2 bridging rules all at the new location
507 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host5, host1));
508 assertEquals(4, ROUTING_TABLE.size());
509 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
510 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
511 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
512 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
513 assertEquals(2, BRIDGING_TABLE.size());
514 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
515 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
516
Charles Chand9265a32017-06-16 15:19:24 -0700517 // Move the host to LOC12, LOC22 and keep the IP
518 // Expect: 4 routing rules and 2 bridging rules all at the new location
Charles Chan4b5769a2018-04-25 18:51:46 -0400519 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host5));
Charles Chan6c624992017-08-18 17:11:34 -0700520 assertEquals(4, ROUTING_TABLE.size());
521 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
522 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
523 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
524 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
525 assertEquals(2, BRIDGING_TABLE.size());
526 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
527 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chand9265a32017-06-16 15:19:24 -0700528
529 // Move the host to LOC11, LOC21 and change the IP to IP13, IP14 at the same time
530 // Expect: 4 routing rules and 2 bridging rules all at the new location
531 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
Charles Chan6c624992017-08-18 17:11:34 -0700532 assertEquals(4, ROUTING_TABLE.size());
533 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())).portNumber);
534 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP14.toIpPrefix())).portNumber);
535 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())).portNumber);
536 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP14.toIpPrefix())).portNumber);
537 assertEquals(2, BRIDGING_TABLE.size());
538 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
539 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chand9265a32017-06-16 15:19:24 -0700540
541 // Move the host to LOC11, LOC22 and change the IP to IP12, IP13 at the same time
542 // Expect: 4 routing rules and 2 bridging rules all at the new location
543 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host4, host3));
Charles Chan6c624992017-08-18 17:11:34 -0700544 assertEquals(4, ROUTING_TABLE.size());
545 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
546 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())).portNumber);
547 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
548 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())).portNumber);
549 assertEquals(2, BRIDGING_TABLE.size());
550 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
551 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan114aec72017-06-19 14:00:53 -0700552 }
553
554 @Test
Charles Chan6d43c162018-10-11 12:35:36 -0700555 public void testDualHomedHostMoveTransient() {
556 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
557 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
558 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
559 Sets.newHashSet(HOST_LOC32, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
560 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
561
562 // Mock DefaultRoutingHandler
563 DefaultRoutingHandler mockDefaultRoutingHandler = createMock(DefaultRoutingHandler.class);
564 hostHandler.srManager.defaultRoutingHandler = mockDefaultRoutingHandler;
565
566 // Host moved from [1A/1, 1B/1] to [1A/2, 1B/1]
567 // We should expect only one bridging flow and one routing flow programmed on 1A
568 mockDefaultRoutingHandler.populateBridging(DEV3, P2, HOST_MAC, HOST_VLAN_UNTAGGED);
569 expectLastCall().times(1);
Ruchi Sahota71bcb4e2019-01-28 01:08:18 +0000570 mockDefaultRoutingHandler.populateRoute(DEV3, HOST_IP11.toIpPrefix(), HOST_MAC, HOST_VLAN_UNTAGGED, P2, true);
Charles Chan6d43c162018-10-11 12:35:36 -0700571 expectLastCall().times(1);
572 replay(mockDefaultRoutingHandler);
573
574 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
575 verify(mockDefaultRoutingHandler);
576 }
577
578 @Test
Charles Chan6e90fbb2018-07-23 15:27:34 -0700579 public void testHostMoveToInvalidLocation() {
Charles Chanabfe7e02017-08-09 16:50:15 -0700580 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
581 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
582 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
583 Sets.newHashSet(HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
584
585 // Add a host
586 // Expect: add one new routing rule, one new bridging rule
587 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700588 assertEquals(1, ROUTING_TABLE.size());
589 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
590 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
591 assertEquals(1, BRIDGING_TABLE.size());
592 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
593 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanabfe7e02017-08-09 16:50:15 -0700594
595 // Move the host to an invalid location
596 // Expect: Old flow is removed. New flow is not created
597 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700598 assertEquals(0, ROUTING_TABLE.size());
599 assertEquals(0, BRIDGING_TABLE.size());
Charles Chanabfe7e02017-08-09 16:50:15 -0700600
601 // Move the host to a valid location
602 // Expect: add one new routing rule, one new bridging rule
603 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
Charles Chan6c624992017-08-18 17:11:34 -0700604 assertEquals(1, ROUTING_TABLE.size());
605 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
606 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
607 assertEquals(1, BRIDGING_TABLE.size());
608 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
609 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanabfe7e02017-08-09 16:50:15 -0700610 }
611
612 @Test
Charles Chan6e90fbb2018-07-23 15:27:34 -0700613 public void testDualHomedHostMoveToInvalidLocation() {
Charles Chanabfe7e02017-08-09 16:50:15 -0700614 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
615 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
616 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
617 Sets.newHashSet(HOST_LOC11, HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
618 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
619 Sets.newHashSet(HOST_LOC61, HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
620
621 // Add a host
622 // Expect: add two new routing rules, two new bridging rules
623 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700624 assertEquals(2, ROUTING_TABLE.size());
625 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
626 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
627 assertEquals(2, BRIDGING_TABLE.size());
628 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
629 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanabfe7e02017-08-09 16:50:15 -0700630
631 // Move first host location to an invalid location
632 // Expect: One routing and one bridging flow
633 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700634 assertEquals(1, ROUTING_TABLE.size());
635 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
636 assertEquals(1, BRIDGING_TABLE.size());
637 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanabfe7e02017-08-09 16:50:15 -0700638
639 // Move second host location to an invalid location
640 // Expect: No routing or bridging rule
641 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
Charles Chan6c624992017-08-18 17:11:34 -0700642 assertEquals(0, ROUTING_TABLE.size());
643 assertEquals(0, BRIDGING_TABLE.size());
Charles Chanabfe7e02017-08-09 16:50:15 -0700644
645 // Move second host location back to a valid location
646 // Expect: One routing and one bridging flow
647 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host3));
Charles Chan6c624992017-08-18 17:11:34 -0700648 assertEquals(1, ROUTING_TABLE.size());
649 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
650 assertEquals(1, BRIDGING_TABLE.size());
651 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanabfe7e02017-08-09 16:50:15 -0700652
653 // Move first host location back to a valid location
654 // Expect: Two routing and two bridging flow
655 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
Charles Chan6c624992017-08-18 17:11:34 -0700656 assertEquals(2, ROUTING_TABLE.size());
657 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
658 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
659 assertEquals(2, BRIDGING_TABLE.size());
660 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
661 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanabfe7e02017-08-09 16:50:15 -0700662 }
663
664 @Test
Charles Chan6e90fbb2018-07-23 15:27:34 -0700665 public void testDualHomingSingleLocationFail() {
Charles Chan3ed34d82017-06-22 18:03:14 -0700666 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
667 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
668 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
669 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
670
671 // Add a host
672 // Expect: add four new routing rules, two new bridging rules
673 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700674 assertEquals(4, ROUTING_TABLE.size());
675 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
676 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
677 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
678 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
679 assertEquals(2, BRIDGING_TABLE.size());
680 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
681 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan3ed34d82017-06-22 18:03:14 -0700682
683 // Host becomes single-homed
684 // Expect: redirect flows from host location to pair link
685 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700686 assertEquals(4, ROUTING_TABLE.size());
687 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
688 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
689 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
690 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
691 assertEquals(2, BRIDGING_TABLE.size());
692 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
693 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan3ed34d82017-06-22 18:03:14 -0700694
695 // Host becomes dual-homed again
696 // Expect: Redirect flows from pair link back to host location
697 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
Charles Chan6c624992017-08-18 17:11:34 -0700698 assertEquals(4, ROUTING_TABLE.size());
699 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
700 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
Charles Chan873661e2017-11-30 15:37:50 -0800701 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
702 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
Charles Chanfbcb8812018-04-18 18:41:05 -0700703 assertEquals(2, BRIDGING_TABLE.size());
704 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan6c624992017-08-18 17:11:34 -0700705 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan3ed34d82017-06-22 18:03:14 -0700706 }
707
708 @Test
Charles Chan6e90fbb2018-07-23 15:27:34 -0700709 public void testDualHomingBothLocationFail() {
Charles Chan3ed34d82017-06-22 18:03:14 -0700710 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
711 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
712 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
713 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
714
715 // Add a host
716 // Expect: add four new routing rules, two new bridging rules
717 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700718 assertEquals(4, ROUTING_TABLE.size());
719 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
720 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
721 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
722 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
723 assertEquals(2, BRIDGING_TABLE.size());
724 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
725 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan3ed34d82017-06-22 18:03:14 -0700726
727 // Host becomes single-homed
728 // Expect: redirect flows from host location to pair link
729 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700730 assertEquals(4, ROUTING_TABLE.size());
731 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
732 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
733 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
734 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
735 assertEquals(2, BRIDGING_TABLE.size());
736 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
737 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan3ed34d82017-06-22 18:03:14 -0700738
739 // Host loses both locations
740 // Expect: Remove last location and all previous redirection flows
741 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, host2));
Charles Chan6c624992017-08-18 17:11:34 -0700742 assertEquals(0, ROUTING_TABLE.size());
743 assertEquals(0, BRIDGING_TABLE.size());
Charles Chan3ed34d82017-06-22 18:03:14 -0700744 }
745
746 @Test
Charles Chan6e90fbb2018-07-23 15:27:34 -0700747 public void testHostUpdated() {
Charles Chan114aec72017-06-19 14:00:53 -0700748 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700749 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan114aec72017-06-19 14:00:53 -0700750 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700751 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP21), false);
Charles Chan114aec72017-06-19 14:00:53 -0700752 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chand9265a32017-06-16 15:19:24 -0700753 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP12), false);
Charles Chan114aec72017-06-19 14:00:53 -0700754
755 // Add a host
Charles Chand9265a32017-06-16 15:19:24 -0700756 // Expect: add one new routing rule. Add one new bridging rule.
Charles Chan114aec72017-06-19 14:00:53 -0700757 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700758 assertEquals(1, ROUTING_TABLE.size());
759 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
760 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
761 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
762 assertEquals(1, BRIDGING_TABLE.size());
763 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(HOST_LOC11.deviceId(), HOST_MAC,
764 INTF_VLAN_UNTAGGED)));
Charles Chan114aec72017-06-19 14:00:53 -0700765
766 // Update the host IP to same subnet
767 // Expect: update routing rule with new IP. No change to bridging rule.
768 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700769 assertEquals(1, ROUTING_TABLE.size());
770 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
771 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
772 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
773 assertEquals(1, BRIDGING_TABLE.size());
774 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan114aec72017-06-19 14:00:53 -0700775
776 // Update the host IP to different subnet
777 // Expect: Remove routing rule. No change to bridging rule.
778 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host3));
Charles Chan6c624992017-08-18 17:11:34 -0700779 assertEquals(0, ROUTING_TABLE.size());
780 assertEquals(1, BRIDGING_TABLE.size());
781 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chand9265a32017-06-16 15:19:24 -0700782 }
783
784 @Test
Charles Chan6e90fbb2018-07-23 15:27:34 -0700785 public void testDelayedIpAndLocation() {
Charles Chanb3c1faf2017-11-20 08:46:24 -0800786 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
787 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(), false);
788 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
789 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11), false);
790 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
791 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
792
793 // Add a dual-home host with only one location and no IP
794 // Expect: only bridging redirection works
795 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
796 assertEquals(0, ROUTING_TABLE.size());
797 assertEquals(2, BRIDGING_TABLE.size());
798 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
799 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
800
801 // Discover IP
802 // Expect: routing redirection should also work
Charles Chan873661e2017-11-30 15:37:50 -0800803 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host1));
Charles Chanb3c1faf2017-11-20 08:46:24 -0800804 assertEquals(2, ROUTING_TABLE.size());
805 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
806 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
807 assertEquals(2, BRIDGING_TABLE.size());
808 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
809 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan873661e2017-11-30 15:37:50 -0800810 // Expect probe to be sent out on pair device
Charles Chanc6bcdf92018-06-01 16:33:48 -0700811 assertTrue(mockLocationProbingService.verifyProbe(host2, CP41, ProbeMode.DISCOVER));
Charles Chanb3c1faf2017-11-20 08:46:24 -0800812
813 // Discover location
814 // Expect: cancel all redirections
Charles Chan873661e2017-11-30 15:37:50 -0800815 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
Charles Chanb3c1faf2017-11-20 08:46:24 -0800816 assertEquals(2, ROUTING_TABLE.size());
817 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
Charles Chanfbcb8812018-04-18 18:41:05 -0700818 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
Charles Chanb3c1faf2017-11-20 08:46:24 -0800819 assertEquals(2, BRIDGING_TABLE.size());
820 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanfbcb8812018-04-18 18:41:05 -0700821 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan873661e2017-11-30 15:37:50 -0800822 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
Charles Chanb3c1faf2017-11-20 08:46:24 -0800823 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
824 }
825
826 @Test
Charles Chan6e90fbb2018-07-23 15:27:34 -0700827 public void testDelayedIpAndLocation2() {
Charles Chanb3c1faf2017-11-20 08:46:24 -0800828 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
829 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(), false);
830 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
831 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(), false);
832 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
833 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
834
835 // Add a dual-home host with only one location and no IP
836 // Expect: only bridging redirection works
837 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
838 assertEquals(0, ROUTING_TABLE.size());
839 assertEquals(2, BRIDGING_TABLE.size());
840 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
841 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
842
843 // Discover Location
844 // Expect: cancel bridging redirections
845 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
846 assertEquals(0, ROUTING_TABLE.size());
847 assertEquals(2, BRIDGING_TABLE.size());
848 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
849 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
850
851 // Discover IP
852 // Expect: add IP rules to both location
853 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host2));
854 assertEquals(2, ROUTING_TABLE.size());
855 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
856 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
857 assertEquals(2, BRIDGING_TABLE.size());
858 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
859 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
860 }
861
862 @Test
Charles Chan6e90fbb2018-07-23 15:27:34 -0700863 public void testDualHomedHostUpdated() {
Charles Chand9265a32017-06-16 15:19:24 -0700864 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
865 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
866 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
867 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP21), false);
868 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
869 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP13, HOST_IP14), false);
870
871 // Add a dual-homed host with two locations and two IPs
872 // Expect: add four new routing rules. Add two new bridging rules
873 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700874 assertEquals(4, ROUTING_TABLE.size());
875 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
876 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
877 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
878 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
879 assertEquals(2, BRIDGING_TABLE.size());
880 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
881 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chand9265a32017-06-16 15:19:24 -0700882
883 // Update both host IPs
884 // Expect: update routing rules with new IP. No change to bridging rule.
885 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host1));
Charles Chan6c624992017-08-18 17:11:34 -0700886 assertEquals(4, ROUTING_TABLE.size());
887 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
888 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
889 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())));
890 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP14.toIpPrefix())));
891 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
892 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
893 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())));
894 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP14.toIpPrefix())));
895 assertEquals(2, BRIDGING_TABLE.size());
896 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
897 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chand9265a32017-06-16 15:19:24 -0700898
899 // Update one of the host IP to different subnet
900 // Expect: update routing rule with new IP. No change to bridging rule.
901 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host3));
Charles Chan6c624992017-08-18 17:11:34 -0700902 assertEquals(2, ROUTING_TABLE.size());
903 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
904 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
905 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
906 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
907 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP21.toIpPrefix())));
908 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
909 assertEquals(2, BRIDGING_TABLE.size());
910 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
911 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chand9265a32017-06-16 15:19:24 -0700912 }
Charles Chan868c9572018-06-15 18:54:18 -0700913
914 @Test
915 public void testVlanForPairPort() {
916 assertEquals(INTF_VLAN_UNTAGGED, hostHandler.vlanForPairPort(VlanId.NONE, CP11));
917 assertEquals(INTF_VLAN_NATIVE, hostHandler.vlanForPairPort(VlanId.NONE, CP13));
918 assertEquals(INTF_VLAN_TAGGED_1, hostHandler.vlanForPairPort(INTF_VLAN_TAGGED_1, CP13));
919 assertNull(hostHandler.vlanForPairPort(INTF_VLAN_UNTAGGED, CP11));
920 assertNull(hostHandler.vlanForPairPort(INTF_VLAN_UNTAGGED, CP13));
921 assertNull(hostHandler.vlanForPairPort(VlanId.NONE, CP51));
922 assertNull(hostHandler.vlanForPairPort(INTF_VLAN_UNTAGGED, CP51));
923 }
Charles Chanbd84dd52018-06-21 19:07:12 -0700924
925 @Test
Charles Chan6e90fbb2018-07-23 15:27:34 -0700926 public void testHostRemovedWithRouteRemoved() {
Charles Chanbd84dd52018-06-21 19:07:12 -0700927 Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
928 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
929
930 // Add a host
931 // Expect: add one routing rule and one bridging rule
932 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
933 assertEquals(1, ROUTING_TABLE.size());
934 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
935 assertEquals(1, BRIDGING_TABLE.size());
936 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
937
938 IpPrefix prefix = IpPrefix.valueOf("55.55.55.0/24");
939
940 // Setting up mock route service
941 RouteService routeService = hostHandler.srManager.routeService;
942 reset(routeService);
943
944 IpAddress nextHopIp2 = IpAddress.valueOf("20.0.0.1");
945 MacAddress nextHopMac2 = MacAddress.valueOf("00:22:33:44:55:66");
946 VlanId nextHopVlan2 = VlanId.NONE;
947
948 Route r1 = new Route(Route.Source.STATIC, prefix, HOST_IP11);
949 ResolvedRoute rr1 = new ResolvedRoute(r1, HOST_MAC, VlanId.NONE);
950 Route r2 = new Route(Route.Source.STATIC, prefix, nextHopIp2);
951 ResolvedRoute rr2 = new ResolvedRoute(r2, nextHopMac2, nextHopVlan2);
952 RouteInfo routeInfo = new RouteInfo(prefix, rr1, Sets.newHashSet(rr1, rr2));
953 RouteTableId routeTableId = new RouteTableId("ipv4");
954
955 expect(routeService.getRouteTables()).andReturn(Sets.newHashSet(routeTableId));
956 expect(routeService.getRoutes(routeTableId)).andReturn(Sets.newHashSet(routeInfo));
957 replay(routeService);
958
959 // Setting up mock device configuration
960 hostHandler.srManager.deviceConfiguration = EasyMock.createNiceMock(DeviceConfiguration.class);
961 DeviceConfiguration deviceConfiguration = hostHandler.srManager.deviceConfiguration;
962 expect(deviceConfiguration.inSameSubnet(CP11, HOST_IP11)).andReturn(true);
963 deviceConfiguration.removeSubnet(CP11, prefix);
964 expectLastCall();
965 replay(deviceConfiguration);
966
967 // Remove the host
968 // Expect: add the routing rule and the bridging rule
969 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, subject));
970 assertEquals(0, ROUTING_TABLE.size());
971 assertEquals(0, BRIDGING_TABLE.size());
972
973 // Expect: subnet is removed from device config
974 verify(deviceConfiguration);
975 }
Charles Chan6e90fbb2018-07-23 15:27:34 -0700976
977 @Test
978 public void testHostProbing() {
979 // Case: [1A/1, 1B/1] -> [1A/2, 1B/1]
980 // Expect: DISCOVER probe should be sent to every port on 1B that has the same VLAN as 1A/2
981 // VERIFY probe should be sent to 1B/1
982 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
983 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
984 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
985 Sets.newHashSet(HOST_LOC32, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
986 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
987
988 hostHandler.srManager.probingService = createMock(HostProbingService.class);
989 hostHandler.srManager.probingService.probeHost(host2, CP41, ProbeMode.DISCOVER);
990 expectLastCall();
991 hostHandler.srManager.probingService.probeHost(host2, CP42, ProbeMode.DISCOVER);
992 expectLastCall();
993 hostHandler.srManager.probingService.probeHost(host2, CP41, ProbeMode.VERIFY);
994 expectLastCall();
995 replay(hostHandler.srManager.probingService);
996
997 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
998
999 verify(hostHandler.srManager.probingService);
1000 }
Ray Milkeyc2d43be2017-08-03 11:58:29 -07001001}