blob: d0ca6cd8693832b7ac20094b1d9f9e9a69ff3a2a [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 Chan5145de22018-10-11 12:35:36 -0700551 public void testDualHomedHostMoveTransient() {
552 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
553 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
554 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
555 Sets.newHashSet(HOST_LOC32, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
556 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
557
558 // Mock DefaultRoutingHandler
559 DefaultRoutingHandler mockDefaultRoutingHandler = createMock(DefaultRoutingHandler.class);
560 hostHandler.srManager.defaultRoutingHandler = mockDefaultRoutingHandler;
561
562 // Host moved from [1A/1, 1B/1] to [1A/2, 1B/1]
563 // We should expect only one bridging flow and one routing flow programmed on 1A
564 mockDefaultRoutingHandler.populateBridging(DEV3, P2, HOST_MAC, HOST_VLAN_UNTAGGED);
565 expectLastCall().times(1);
Ruchi Sahotaef0761c2019-01-28 01:08:18 +0000566 mockDefaultRoutingHandler.populateRoute(DEV3, HOST_IP11.toIpPrefix(), HOST_MAC, HOST_VLAN_UNTAGGED, P2, true);
Charles Chan5145de22018-10-11 12:35:36 -0700567 expectLastCall().times(1);
568 replay(mockDefaultRoutingHandler);
569
570 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
571 verify(mockDefaultRoutingHandler);
572 }
573
574 @Test
Charles Chanf82d1552018-07-23 15:27:34 -0700575 public void testHostMoveToInvalidLocation() {
Charles Chan9f08b102017-08-09 16:50:15 -0700576 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
577 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
578 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
579 Sets.newHashSet(HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
580
581 // Add a host
582 // Expect: add one new routing rule, one new bridging rule
583 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700584 assertEquals(1, ROUTING_TABLE.size());
585 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
586 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
587 assertEquals(1, BRIDGING_TABLE.size());
588 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
589 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan9f08b102017-08-09 16:50:15 -0700590
591 // Move the host to an invalid location
592 // Expect: Old flow is removed. New flow is not created
593 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700594 assertEquals(0, ROUTING_TABLE.size());
595 assertEquals(0, BRIDGING_TABLE.size());
Charles Chan9f08b102017-08-09 16:50:15 -0700596
597 // Move the host to a valid location
598 // Expect: add one new routing rule, one new bridging rule
599 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700600 assertEquals(1, ROUTING_TABLE.size());
601 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
602 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
603 assertEquals(1, BRIDGING_TABLE.size());
604 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
605 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan9f08b102017-08-09 16:50:15 -0700606 }
607
608 @Test
Charles Chanf82d1552018-07-23 15:27:34 -0700609 public void testDualHomedHostMoveToInvalidLocation() {
Charles Chan9f08b102017-08-09 16:50:15 -0700610 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
611 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
612 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
613 Sets.newHashSet(HOST_LOC11, HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
614 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
615 Sets.newHashSet(HOST_LOC61, HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
616
617 // Add a host
618 // Expect: add two new routing rules, two new bridging rules
619 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700620 assertEquals(2, ROUTING_TABLE.size());
621 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
622 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
623 assertEquals(2, BRIDGING_TABLE.size());
624 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
625 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan9f08b102017-08-09 16:50:15 -0700626
627 // Move first host location to an invalid location
628 // Expect: One routing and one bridging flow
629 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700630 assertEquals(1, ROUTING_TABLE.size());
631 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
632 assertEquals(1, BRIDGING_TABLE.size());
633 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan9f08b102017-08-09 16:50:15 -0700634
635 // Move second host location to an invalid location
636 // Expect: No routing or bridging rule
637 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700638 assertEquals(0, ROUTING_TABLE.size());
639 assertEquals(0, BRIDGING_TABLE.size());
Charles Chan9f08b102017-08-09 16:50:15 -0700640
641 // Move second host location back to a valid location
642 // Expect: One routing and one bridging flow
643 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host3));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700644 assertEquals(1, ROUTING_TABLE.size());
645 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
646 assertEquals(1, BRIDGING_TABLE.size());
647 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan9f08b102017-08-09 16:50:15 -0700648
649 // Move first host location back to a valid location
650 // Expect: Two routing and two bridging flow
651 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700652 assertEquals(2, ROUTING_TABLE.size());
653 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
654 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
655 assertEquals(2, BRIDGING_TABLE.size());
656 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
657 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan9f08b102017-08-09 16:50:15 -0700658 }
659
660 @Test
Charles Chanf82d1552018-07-23 15:27:34 -0700661 public void testDualHomingSingleLocationFail() {
Charles Chan65238242017-06-22 18:03:14 -0700662 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
663 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
664 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
665 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
666
667 // Add a host
668 // Expect: add four new routing rules, two new bridging rules
669 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
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);
673 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);
675 assertEquals(2, BRIDGING_TABLE.size());
676 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
677 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan65238242017-06-22 18:03:14 -0700678
679 // Host becomes single-homed
680 // Expect: redirect flows from host location to pair link
681 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700682 assertEquals(4, ROUTING_TABLE.size());
683 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
684 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
685 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
686 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
687 assertEquals(2, BRIDGING_TABLE.size());
688 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
689 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan65238242017-06-22 18:03:14 -0700690
691 // Host becomes dual-homed again
692 // Expect: Redirect flows from pair link back to host location
693 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700694 assertEquals(4, ROUTING_TABLE.size());
695 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
696 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
Charles Chan47933752017-11-30 15:37:50 -0800697 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
698 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
Charles Chan50bb6ef2018-04-18 18:41:05 -0700699 assertEquals(2, BRIDGING_TABLE.size());
700 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan1a3b02a2017-08-18 17:11:34 -0700701 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan65238242017-06-22 18:03:14 -0700702 }
703
704 @Test
Charles Chanf82d1552018-07-23 15:27:34 -0700705 public void testDualHomingBothLocationFail() {
Charles Chan65238242017-06-22 18:03:14 -0700706 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
707 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
708 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
709 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
710
711 // Add a host
712 // Expect: add four new routing rules, two new bridging rules
713 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700714 assertEquals(4, ROUTING_TABLE.size());
715 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
716 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
717 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
718 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
719 assertEquals(2, BRIDGING_TABLE.size());
720 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
721 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan65238242017-06-22 18:03:14 -0700722
723 // Host becomes single-homed
724 // Expect: redirect flows from host location to pair link
725 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700726 assertEquals(4, ROUTING_TABLE.size());
727 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
728 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
729 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
730 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
731 assertEquals(2, BRIDGING_TABLE.size());
732 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
733 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan65238242017-06-22 18:03:14 -0700734
735 // Host loses both locations
736 // Expect: Remove last location and all previous redirection flows
737 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, host2));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700738 assertEquals(0, ROUTING_TABLE.size());
739 assertEquals(0, BRIDGING_TABLE.size());
Charles Chan65238242017-06-22 18:03:14 -0700740 }
741
742 @Test
Charles Chanf82d1552018-07-23 15:27:34 -0700743 public void testHostUpdated() {
Charles Chan2e2e3402017-06-19 14:00:53 -0700744 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700745 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700746 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700747 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP21), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700748 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700749 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP12), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700750
751 // Add a host
Charles Chanf9a52702017-06-16 15:19:24 -0700752 // Expect: add one new routing rule. Add one new bridging rule.
Charles Chan2e2e3402017-06-19 14:00:53 -0700753 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700754 assertEquals(1, ROUTING_TABLE.size());
755 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
756 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
757 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
758 assertEquals(1, BRIDGING_TABLE.size());
759 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(HOST_LOC11.deviceId(), HOST_MAC,
760 INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700761
762 // Update the host IP to same subnet
763 // Expect: update routing rule with new IP. No change to bridging rule.
764 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700765 assertEquals(1, ROUTING_TABLE.size());
766 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
767 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
768 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
769 assertEquals(1, BRIDGING_TABLE.size());
770 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700771
772 // Update the host IP to different subnet
773 // Expect: Remove routing rule. No change to bridging rule.
774 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host3));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700775 assertEquals(0, ROUTING_TABLE.size());
776 assertEquals(1, BRIDGING_TABLE.size());
777 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700778 }
779
780 @Test
Charles Chanf82d1552018-07-23 15:27:34 -0700781 public void testDelayedIpAndLocation() {
Charles Chan3d650a62017-11-20 08:46:24 -0800782 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
783 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(), false);
784 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
785 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11), false);
786 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
787 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
788
789 // Add a dual-home host with only one location and no IP
790 // Expect: only bridging redirection works
791 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
792 assertEquals(0, ROUTING_TABLE.size());
793 assertEquals(2, BRIDGING_TABLE.size());
794 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
795 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
796
797 // Discover IP
798 // Expect: routing redirection should also work
Charles Chan47933752017-11-30 15:37:50 -0800799 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host1));
Charles Chan3d650a62017-11-20 08:46:24 -0800800 assertEquals(2, ROUTING_TABLE.size());
801 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
802 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
803 assertEquals(2, BRIDGING_TABLE.size());
804 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
805 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan47933752017-11-30 15:37:50 -0800806 // Expect probe to be sent out on pair device
Charles Chanff79dd92018-06-01 16:33:48 -0700807 assertTrue(mockLocationProbingService.verifyProbe(host2, CP41, ProbeMode.DISCOVER));
Charles Chan3d650a62017-11-20 08:46:24 -0800808
809 // Discover location
810 // Expect: cancel all redirections
Charles Chan47933752017-11-30 15:37:50 -0800811 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
Charles Chan3d650a62017-11-20 08:46:24 -0800812 assertEquals(2, ROUTING_TABLE.size());
813 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
Charles Chan50bb6ef2018-04-18 18:41:05 -0700814 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
Charles Chan3d650a62017-11-20 08:46:24 -0800815 assertEquals(2, BRIDGING_TABLE.size());
816 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan50bb6ef2018-04-18 18:41:05 -0700817 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan47933752017-11-30 15:37:50 -0800818 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
Charles Chan3d650a62017-11-20 08:46:24 -0800819 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
820 }
821
822 @Test
Charles Chanf82d1552018-07-23 15:27:34 -0700823 public void testDelayedIpAndLocation2() {
Charles Chan3d650a62017-11-20 08:46:24 -0800824 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
825 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(), false);
826 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
827 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(), false);
828 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
829 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
830
831 // Add a dual-home host with only one location and no IP
832 // Expect: only bridging redirection works
833 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
834 assertEquals(0, ROUTING_TABLE.size());
835 assertEquals(2, BRIDGING_TABLE.size());
836 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
837 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
838
839 // Discover Location
840 // Expect: cancel bridging redirections
841 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
842 assertEquals(0, ROUTING_TABLE.size());
843 assertEquals(2, BRIDGING_TABLE.size());
844 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
845 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
846
847 // Discover IP
848 // Expect: add IP rules to both location
849 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host2));
850 assertEquals(2, ROUTING_TABLE.size());
851 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
852 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
853 assertEquals(2, BRIDGING_TABLE.size());
854 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
855 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
856 }
857
858 @Test
Charles Chanf82d1552018-07-23 15:27:34 -0700859 public void testDualHomedHostUpdated() {
Charles Chanf9a52702017-06-16 15:19:24 -0700860 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
861 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
862 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
863 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP21), false);
864 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
865 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP13, HOST_IP14), false);
866
867 // Add a dual-homed host with two locations and two IPs
868 // Expect: add four new routing rules. Add two new bridging rules
869 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700870 assertEquals(4, ROUTING_TABLE.size());
871 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
872 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
873 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
874 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
875 assertEquals(2, BRIDGING_TABLE.size());
876 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
877 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700878
879 // Update both host IPs
880 // Expect: update routing rules with new IP. No change to bridging rule.
881 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700882 assertEquals(4, ROUTING_TABLE.size());
883 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
884 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
885 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())));
886 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP14.toIpPrefix())));
887 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
888 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
889 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())));
890 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP14.toIpPrefix())));
891 assertEquals(2, BRIDGING_TABLE.size());
892 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
893 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700894
895 // Update one of the host IP to different subnet
896 // Expect: update routing rule with new IP. No change to bridging rule.
897 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host3));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700898 assertEquals(2, ROUTING_TABLE.size());
899 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
900 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
901 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
902 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
903 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP21.toIpPrefix())));
904 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
905 assertEquals(2, BRIDGING_TABLE.size());
906 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
907 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700908 }
Charles Chanf76de302018-06-15 18:54:18 -0700909
910 @Test
911 public void testVlanForPairPort() {
912 assertEquals(INTF_VLAN_UNTAGGED, hostHandler.vlanForPairPort(VlanId.NONE, CP11));
913 assertEquals(INTF_VLAN_NATIVE, hostHandler.vlanForPairPort(VlanId.NONE, CP13));
914 assertEquals(INTF_VLAN_TAGGED_1, hostHandler.vlanForPairPort(INTF_VLAN_TAGGED_1, CP13));
915 assertNull(hostHandler.vlanForPairPort(INTF_VLAN_UNTAGGED, CP11));
916 assertNull(hostHandler.vlanForPairPort(INTF_VLAN_UNTAGGED, CP13));
917 assertNull(hostHandler.vlanForPairPort(VlanId.NONE, CP51));
918 assertNull(hostHandler.vlanForPairPort(INTF_VLAN_UNTAGGED, CP51));
919 }
Charles Chan4d639392018-06-21 19:07:12 -0700920
921 @Test
Charles Chanf82d1552018-07-23 15:27:34 -0700922 public void testHostRemovedWithRouteRemoved() {
Charles Chan4d639392018-06-21 19:07:12 -0700923 Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
924 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
925
926 // Add a host
927 // Expect: add one routing rule and one bridging rule
928 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
929 assertEquals(1, ROUTING_TABLE.size());
930 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
931 assertEquals(1, BRIDGING_TABLE.size());
932 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
933
934 IpPrefix prefix = IpPrefix.valueOf("55.55.55.0/24");
935
936 // Setting up mock route service
937 RouteService routeService = hostHandler.srManager.routeService;
938 reset(routeService);
939
940 IpAddress nextHopIp2 = IpAddress.valueOf("20.0.0.1");
941 MacAddress nextHopMac2 = MacAddress.valueOf("00:22:33:44:55:66");
942 VlanId nextHopVlan2 = VlanId.NONE;
943
944 Route r1 = new Route(Route.Source.STATIC, prefix, HOST_IP11);
945 ResolvedRoute rr1 = new ResolvedRoute(r1, HOST_MAC, VlanId.NONE);
946 Route r2 = new Route(Route.Source.STATIC, prefix, nextHopIp2);
947 ResolvedRoute rr2 = new ResolvedRoute(r2, nextHopMac2, nextHopVlan2);
948 RouteInfo routeInfo = new RouteInfo(prefix, rr1, Sets.newHashSet(rr1, rr2));
949 RouteTableId routeTableId = new RouteTableId("ipv4");
950
951 expect(routeService.getRouteTables()).andReturn(Sets.newHashSet(routeTableId));
952 expect(routeService.getRoutes(routeTableId)).andReturn(Sets.newHashSet(routeInfo));
953 replay(routeService);
954
955 // Setting up mock device configuration
956 hostHandler.srManager.deviceConfiguration = EasyMock.createNiceMock(DeviceConfiguration.class);
957 DeviceConfiguration deviceConfiguration = hostHandler.srManager.deviceConfiguration;
958 expect(deviceConfiguration.inSameSubnet(CP11, HOST_IP11)).andReturn(true);
959 deviceConfiguration.removeSubnet(CP11, prefix);
960 expectLastCall();
961 replay(deviceConfiguration);
962
963 // Remove the host
964 // Expect: add the routing rule and the bridging rule
965 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, subject));
966 assertEquals(0, ROUTING_TABLE.size());
967 assertEquals(0, BRIDGING_TABLE.size());
968
969 // Expect: subnet is removed from device config
970 verify(deviceConfiguration);
971 }
Charles Chanf82d1552018-07-23 15:27:34 -0700972
973 @Test
974 public void testHostProbing() {
975 // Case: [1A/1, 1B/1] -> [1A/2, 1B/1]
976 // Expect: DISCOVER probe should be sent to every port on 1B that has the same VLAN as 1A/2
977 // VERIFY probe should be sent to 1B/1
978 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
979 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
980 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
981 Sets.newHashSet(HOST_LOC32, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
982 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
983
984 hostHandler.srManager.probingService = createMock(HostProbingService.class);
985 hostHandler.srManager.probingService.probeHost(host2, CP41, ProbeMode.DISCOVER);
986 expectLastCall();
987 hostHandler.srManager.probingService.probeHost(host2, CP42, ProbeMode.DISCOVER);
988 expectLastCall();
989 hostHandler.srManager.probingService.probeHost(host2, CP41, ProbeMode.VERIFY);
990 expectLastCall();
991 replay(hostHandler.srManager.probingService);
992
993 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
994
995 verify(hostHandler.srManager.probingService);
996 }
Ray Milkeyfacf2862017-08-03 11:58:29 -0700997}