blob: 98f6fd04becefa6b8bdc0f9624ce2dc9a8e39204 [file] [log] [blame]
Charles Chan2e2e3402017-06-19 14:00:53 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Charles Chan2e2e3402017-06-19 14:00:53 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.segmentrouting;
18
Charles Chan65238242017-06-22 18:03:14 -070019import com.fasterxml.jackson.databind.JsonNode;
20import com.fasterxml.jackson.databind.ObjectMapper;
Charles Chan2e2e3402017-06-19 14:00:53 -070021import com.google.common.collect.Lists;
22import com.google.common.collect.Maps;
23import com.google.common.collect.Sets;
24import org.junit.Before;
25import org.junit.Test;
26import org.onlab.packet.IpAddress;
27import org.onlab.packet.IpPrefix;
28import org.onlab.packet.MacAddress;
29import org.onlab.packet.VlanId;
Charles Chan1a3b02a2017-08-18 17:11:34 -070030import org.onosproject.net.config.ConfigApplyDelegate;
Ray Milkeyfacf2862017-08-03 11:58:29 -070031import org.onosproject.net.intf.Interface;
Charles Chan2e2e3402017-06-19 14:00:53 -070032import org.onosproject.net.ConnectPoint;
33import org.onosproject.net.DefaultHost;
34import org.onosproject.net.DeviceId;
35import org.onosproject.net.Host;
36import org.onosproject.net.HostId;
37import org.onosproject.net.HostLocation;
38import org.onosproject.net.PortNumber;
39import org.onosproject.net.config.NetworkConfigRegistryAdapter;
Charles Chan2e2e3402017-06-19 14:00:53 -070040import org.onosproject.net.flow.TrafficTreatment;
Charles Chan2e2e3402017-06-19 14:00:53 -070041import org.onosproject.net.host.HostEvent;
42import org.onosproject.net.host.InterfaceIpAddress;
43import org.onosproject.net.provider.ProviderId;
44import org.onosproject.segmentrouting.config.DeviceConfiguration;
Charles Chan65238242017-06-22 18:03:14 -070045import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
Charles Chan2e2e3402017-06-19 14:00:53 -070046
47import java.util.Map;
Charles Chan2e2e3402017-06-19 14:00:53 -070048import java.util.Set;
Charles Chan2e2e3402017-06-19 14:00:53 -070049
50import static org.junit.Assert.*;
51
Charles Chan1a3b02a2017-08-18 17:11:34 -070052/**r
Charles Chan2e2e3402017-06-19 14:00:53 -070053 * Unit test for {@link HostHandler}.
54 */
55public class HostHandlerTest {
Charles Chan2e2e3402017-06-19 14:00:53 -070056 private HostHandler hostHandler;
57
58 // Mocked routing and bridging tables
Charles Chan1a3b02a2017-08-18 17:11:34 -070059 private static final Map<MockBridgingTableKey, MockBridgingTableValue> BRIDGING_TABLE =
60 Maps.newConcurrentMap();
61 private static final Map<MockRoutingTableKey, MockRoutingTableValue> ROUTING_TABLE =
62 Maps.newConcurrentMap();
Charles Chan2fde6d42017-08-23 14:46:43 -070063 private static final Map<ConnectPoint, Set<IpPrefix>> SUBNET_TABLE = Maps.newConcurrentMap();
Charles Chan2e2e3402017-06-19 14:00:53 -070064 // Mocked Next Id
Charles Chan1a3b02a2017-08-18 17:11:34 -070065 private static final Map<Integer, TrafficTreatment> NEXT_TABLE = Maps.newConcurrentMap();
Charles Chan2e2e3402017-06-19 14:00:53 -070066
Charles Chanf9a52702017-06-16 15:19:24 -070067 // Host Mac, VLAN
Charles Chan2e2e3402017-06-19 14:00:53 -070068 private static final ProviderId PROVIDER_ID = ProviderId.NONE;
69 private static final MacAddress HOST_MAC = MacAddress.valueOf("00:00:00:00:00:01");
70 private static final VlanId HOST_VLAN_UNTAGGED = VlanId.NONE;
71 private static final HostId HOST_ID_UNTAGGED = HostId.hostId(HOST_MAC, HOST_VLAN_UNTAGGED);
72 private static final VlanId HOST_VLAN_TAGGED = VlanId.vlanId((short) 20);
73 private static final HostId HOST_ID_TAGGED = HostId.hostId(HOST_MAC, HOST_VLAN_TAGGED);
Charles Chanf9a52702017-06-16 15:19:24 -070074 // Host IP
75 private static final IpAddress HOST_IP11 = IpAddress.valueOf("10.0.1.1");
76 private static final IpAddress HOST_IP21 = IpAddress.valueOf("10.0.2.1");
77 private static final IpAddress HOST_IP12 = IpAddress.valueOf("10.0.1.2");
78 private static final IpAddress HOST_IP13 = IpAddress.valueOf("10.0.1.3");
79 private static final IpAddress HOST_IP14 = IpAddress.valueOf("10.0.1.4");
Charles Chan8e786b52017-09-12 18:57:47 -070080 private static final IpAddress HOST_IP32 = IpAddress.valueOf("10.0.3.2");
Charles Chanf9a52702017-06-16 15:19:24 -070081 // Device
82 private static final DeviceId DEV1 = DeviceId.deviceId("of:0000000000000001");
83 private static final DeviceId DEV2 = DeviceId.deviceId("of:0000000000000002");
Charles Chan9f08b102017-08-09 16:50:15 -070084 private static final DeviceId DEV3 = DeviceId.deviceId("of:0000000000000003");
85 private static final DeviceId DEV4 = DeviceId.deviceId("of:0000000000000004");
86 private static final DeviceId DEV5 = DeviceId.deviceId("of:0000000000000005");
87 private static final DeviceId DEV6 = DeviceId.deviceId("of:0000000000000006");
Charles Chanf9a52702017-06-16 15:19:24 -070088 // Port
89 private static final PortNumber P1 = PortNumber.portNumber(1);
90 private static final PortNumber P2 = PortNumber.portNumber(2);
91 private static final PortNumber P3 = PortNumber.portNumber(3);
Charles Chan65238242017-06-22 18:03:14 -070092 private static final PortNumber P9 = PortNumber.portNumber(9);
Charles Chanf9a52702017-06-16 15:19:24 -070093 // Connect Point
94 private static final ConnectPoint CP11 = new ConnectPoint(DEV1, P1);
95 private static final HostLocation HOST_LOC11 = new HostLocation(CP11, 0);
96 private static final ConnectPoint CP12 = new ConnectPoint(DEV1, P2);
97 private static final HostLocation HOST_LOC12 = new HostLocation(CP12, 0);
98 private static final ConnectPoint CP13 = new ConnectPoint(DEV1, P3);
99 private static final HostLocation HOST_LOC13 = new HostLocation(CP13, 0);
100 private static final ConnectPoint CP21 = new ConnectPoint(DEV2, P1);
101 private static final HostLocation HOST_LOC21 = new HostLocation(CP21, 0);
102 private static final ConnectPoint CP22 = new ConnectPoint(DEV2, P2);
103 private static final HostLocation HOST_LOC22 = new HostLocation(CP22, 0);
Charles Chan65238242017-06-22 18:03:14 -0700104 // Connect Point for dual-homed host failover
105 private static final ConnectPoint CP31 = new ConnectPoint(DEV3, P1);
106 private static final HostLocation HOST_LOC31 = new HostLocation(CP31, 0);
Charles Chan8e786b52017-09-12 18:57:47 -0700107 private static final ConnectPoint CP32 = new ConnectPoint(DEV3, P2);
108 private static final HostLocation HOST_LOC32 = new HostLocation(CP32, 0);
Charles Chan65238242017-06-22 18:03:14 -0700109 private static final ConnectPoint CP41 = new ConnectPoint(DEV4, P1);
110 private static final HostLocation HOST_LOC41 = new HostLocation(CP41, 0);
111 private static final ConnectPoint CP39 = new ConnectPoint(DEV3, P9);
112 private static final ConnectPoint CP49 = new ConnectPoint(DEV4, P9);
Charles Chan9f08b102017-08-09 16:50:15 -0700113 // Conenct Point for mastership test
114 private static final ConnectPoint CP51 = new ConnectPoint(DEV5, P1);
115 private static final HostLocation HOST_LOC51 = new HostLocation(CP51, 0);
116 private static final ConnectPoint CP61 = new ConnectPoint(DEV6, P1);
117 private static final HostLocation HOST_LOC61 = new HostLocation(CP61, 0);
Charles Chanf9a52702017-06-16 15:19:24 -0700118 // Interface VLAN
Charles Chan2e2e3402017-06-19 14:00:53 -0700119 private static final VlanId INTF_VLAN_UNTAGGED = VlanId.vlanId((short) 10);
Charles Chan2e2e3402017-06-19 14:00:53 -0700120 private static final Set<VlanId> INTF_VLAN_TAGGED = Sets.newHashSet(VlanId.vlanId((short) 20));
121 private static final VlanId INTF_VLAN_NATIVE = VlanId.vlanId((short) 30);
Charles Chan65238242017-06-22 18:03:14 -0700122 private static final Set<VlanId> INTF_VLAN_PAIR = Sets.newHashSet(VlanId.vlanId((short) 10),
123 VlanId.vlanId((short) 20), VlanId.vlanId((short) 30));
Charles Chan8e786b52017-09-12 18:57:47 -0700124 private static final VlanId INTF_VLAN_OTHER = VlanId.vlanId((short) 40);
Charles Chanf9a52702017-06-16 15:19:24 -0700125 // Interface subnet
126 private static final IpPrefix INTF_PREFIX1 = IpPrefix.valueOf("10.0.1.254/24");
127 private static final IpPrefix INTF_PREFIX2 = IpPrefix.valueOf("10.0.2.254/24");
Charles Chan8e786b52017-09-12 18:57:47 -0700128 private static final IpPrefix INTF_PREFIX3 = IpPrefix.valueOf("10.0.3.254/24");
Charles Chanf9a52702017-06-16 15:19:24 -0700129 private static final InterfaceIpAddress INTF_IP1 =
130 new InterfaceIpAddress(INTF_PREFIX1.address(), INTF_PREFIX1);
131 private static final InterfaceIpAddress INTF_IP2 =
132 new InterfaceIpAddress(INTF_PREFIX2.address(), INTF_PREFIX2);
Charles Chan8e786b52017-09-12 18:57:47 -0700133 private static final InterfaceIpAddress INTF_IP3 =
134 new InterfaceIpAddress(INTF_PREFIX3.address(), INTF_PREFIX3);
Charles Chan1a3b02a2017-08-18 17:11:34 -0700135 // Interfaces
136 private static final Interface INTF11 =
137 new Interface(null, CP11, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
138 INTF_VLAN_UNTAGGED, null, null);
139 private static final Interface INTF12 =
140 new Interface(null, CP12, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
141 INTF_VLAN_UNTAGGED, null, null);
142 private static final Interface INTF13 =
143 new Interface(null, CP13, Lists.newArrayList(INTF_IP2), MacAddress.NONE, null,
144 null, INTF_VLAN_TAGGED, INTF_VLAN_NATIVE);
145 private static final Interface INTF21 =
146 new Interface(null, CP21, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
147 INTF_VLAN_UNTAGGED, null, null);
148 private static final Interface INTF22 =
149 new Interface(null, CP22, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
150 INTF_VLAN_UNTAGGED, null, null);
151 private static final Interface INTF31 =
152 new Interface(null, CP31, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
153 INTF_VLAN_UNTAGGED, null, null);
Charles Chan8e786b52017-09-12 18:57:47 -0700154 private static final Interface INTF32 =
155 new Interface(null, CP32, Lists.newArrayList(INTF_IP3), MacAddress.NONE, null,
156 INTF_VLAN_OTHER, null, null);
Charles Chan1a3b02a2017-08-18 17:11:34 -0700157 private static final Interface INTF39 =
158 new Interface(null, CP39, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
159 null, INTF_VLAN_PAIR, null);
160 private static final Interface INTF41 =
161 new Interface(null, CP41, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
162 INTF_VLAN_UNTAGGED, null, null);
163 private static final Interface INTF49 =
164 new Interface(null, CP49, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
165 null, INTF_VLAN_PAIR, null);
Charles Chanf9a52702017-06-16 15:19:24 -0700166 // Host
167 private static final Host HOST1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC,
168 HOST_VLAN_UNTAGGED, Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11),
169 false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700170
Charles Chan1a3b02a2017-08-18 17:11:34 -0700171 // A set of hosts
172 private static final Set<Host> HOSTS = Sets.newHashSet(HOST1);
173 // A set of devices of which we have mastership
174 private static final Set<DeviceId> LOCAL_DEVICES = Sets.newHashSet(DEV1, DEV2, DEV3, DEV4);
175 // A set of interfaces
176 private static final Set<Interface> INTERFACES = Sets.newHashSet(INTF11, INTF12, INTF13, INTF21,
Charles Chan8e786b52017-09-12 18:57:47 -0700177 INTF22, INTF31, INTF32, INTF39, INTF41, INTF49);
Charles Chan1a3b02a2017-08-18 17:11:34 -0700178
Charles Chan2e2e3402017-06-19 14:00:53 -0700179 @Before
180 public void setUp() throws Exception {
Charles Chan1a3b02a2017-08-18 17:11:34 -0700181 // Initialize pairDevice and pairLocalPort config
182 ObjectMapper mapper = new ObjectMapper();
183 ConfigApplyDelegate delegate = config -> { };
184
185 SegmentRoutingDeviceConfig dev3Config = new SegmentRoutingDeviceConfig();
186 JsonNode dev3Tree = mapper.createObjectNode();
187 dev3Config.init(DEV3, "host-handler-test", dev3Tree, mapper, delegate);
188 dev3Config.setPairDeviceId(DEV4).setPairLocalPort(P9);
189
190 SegmentRoutingDeviceConfig dev4Config = new SegmentRoutingDeviceConfig();
191 JsonNode dev4Tree = mapper.createObjectNode();
192 dev4Config.init(DEV4, "host-handler-test", dev4Tree, mapper, delegate);
193 dev4Config.setPairDeviceId(DEV3).setPairLocalPort(P9);
194
195 MockNetworkConfigRegistry mockNetworkConfigRegistry = new MockNetworkConfigRegistry();
196 mockNetworkConfigRegistry.applyConfig(dev3Config);
197 mockNetworkConfigRegistry.applyConfig(dev4Config);
198
199 // Initialize Segment Routing Manager
200 SegmentRoutingManager srManager = new MockSegmentRoutingManager(NEXT_TABLE);
Charles Chan2e2e3402017-06-19 14:00:53 -0700201 srManager.cfgService = new NetworkConfigRegistryAdapter();
202 srManager.deviceConfiguration = new DeviceConfiguration(srManager);
Charles Chan1a3b02a2017-08-18 17:11:34 -0700203 srManager.flowObjectiveService = new MockFlowObjectiveService(BRIDGING_TABLE, NEXT_TABLE);
204 srManager.routingRulePopulator = new MockRoutingRulePopulator(srManager, ROUTING_TABLE);
Charles Chan2fde6d42017-08-23 14:46:43 -0700205 srManager.defaultRoutingHandler = new MockDefaultRoutingHandler(srManager, SUBNET_TABLE);
Charles Chan1a3b02a2017-08-18 17:11:34 -0700206 srManager.interfaceService = new MockInterfaceService(INTERFACES);
207 srManager.mastershipService = new MockMastershipService(LOCAL_DEVICES);
208 srManager.hostService = new MockHostService(HOSTS);
209 srManager.cfgService = mockNetworkConfigRegistry;
Charles Chan2e2e3402017-06-19 14:00:53 -0700210
211 hostHandler = new HostHandler(srManager);
212
Charles Chan1a3b02a2017-08-18 17:11:34 -0700213 ROUTING_TABLE.clear();
214 BRIDGING_TABLE.clear();
Charles Chan2e2e3402017-06-19 14:00:53 -0700215 }
216
217 @Test
218 public void init() throws Exception {
Charles Chanf9a52702017-06-16 15:19:24 -0700219 hostHandler.init(DEV1);
Charles Chan1a3b02a2017-08-18 17:11:34 -0700220 assertEquals(1, ROUTING_TABLE.size());
221 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
222 assertEquals(1, BRIDGING_TABLE.size());
223 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700224
225 hostHandler.init(DEV2);
Charles Chan1a3b02a2017-08-18 17:11:34 -0700226 assertEquals(2, ROUTING_TABLE.size());
227 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
228 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
229 assertEquals(2, BRIDGING_TABLE.size());
230 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
231 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700232 }
233
234 @Test(expected = IllegalArgumentException.class)
235 public void testHostAddedAtWrongLocation() throws Exception {
236 hostHandler.processHostAddedAtLocation(HOST1, HOST_LOC13);
237 }
238
239
240 @Test()
241 public void testHostAddedAtCorrectLocation() throws Exception {
242 hostHandler.processHostAddedAtLocation(HOST1, HOST_LOC11);
Charles Chan1a3b02a2017-08-18 17:11:34 -0700243 assertEquals(1, ROUTING_TABLE.size());
244 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
245 assertEquals(1, BRIDGING_TABLE.size());
246 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700247 }
248
249 @Test
250 public void testHostAdded() throws Exception {
251 Host subject;
252
253 // Untagged host discovered on untagged port
254 // Expect: add one routing rule and one bridging rule
255 subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700256 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700257 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700258 assertEquals(1, ROUTING_TABLE.size());
259 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
260 assertEquals(1, BRIDGING_TABLE.size());
261 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700262
263 // Untagged host discovered on tagged/native port
264 // Expect: add one routing rule and one bridging rule
265 subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700266 Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP21), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700267 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700268 assertEquals(2, ROUTING_TABLE.size());
269 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
270 assertEquals(2, BRIDGING_TABLE.size());
271 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_NATIVE)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700272
273 // Tagged host discovered on untagged port
274 // Expect: ignore the host. No rule is added.
275 subject = new DefaultHost(PROVIDER_ID, HOST_ID_TAGGED, HOST_MAC, HOST_VLAN_TAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700276 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700277 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700278 assertEquals(2, ROUTING_TABLE.size());
279 assertEquals(2, BRIDGING_TABLE.size());
Charles Chan2e2e3402017-06-19 14:00:53 -0700280
281 // Tagged host discovered on tagged port with the same IP
282 // Expect: update existing route, add one bridging rule
283 subject = new DefaultHost(PROVIDER_ID, HOST_ID_TAGGED, HOST_MAC, HOST_VLAN_TAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700284 Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP21), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700285 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700286 assertEquals(2, ROUTING_TABLE.size());
287 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
288 assertEquals(HOST_VLAN_TAGGED, ROUTING_TABLE.get(new MockRoutingTableKey(HOST_LOC13.deviceId(),
Charles Chanf9a52702017-06-16 15:19:24 -0700289 HOST_IP21.toIpPrefix())).vlanId);
Charles Chan1a3b02a2017-08-18 17:11:34 -0700290 assertEquals(3, BRIDGING_TABLE.size());
291 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, HOST_VLAN_TAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700292 }
293
294 @Test
295 public void testDualHomedHostAdded() throws Exception {
296 // Add a dual-homed host that has 2 locations
297 // Expect: add two routing rules and two bridging rules
298 Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
299 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
300 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700301 assertEquals(2, ROUTING_TABLE.size());
302 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
303 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
304 assertEquals(2, BRIDGING_TABLE.size());
305 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
306 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700307 }
308
309 @Test
Charles Chan8e786b52017-09-12 18:57:47 -0700310 public void testSingleHomedHostAddedOnPairLeaf() throws Exception {
311 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
312 Sets.newHashSet(HOST_LOC32), Sets.newHashSet(HOST_IP32), false);
313
314 // Add a single-homed host with one location
315 // Expect: the pair link should not be utilized
316 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
317 assertEquals(1, ROUTING_TABLE.size());
318 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP32.toIpPrefix())).portNumber);
319 assertEquals(1, BRIDGING_TABLE.size());
320 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_OTHER)).portNumber);
321 }
322
323 @Test
324 public void testDualHomedHostAddedOneByOne() throws Exception {
325 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
326 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11), false);
327 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
328 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11), false);
329
330 // Add a dual-homed host with one location
331 // Expect: the pair link is utilized temporarily before the second location is discovered
332 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
333 assertEquals(2, ROUTING_TABLE.size());
334 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
335 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
336 assertEquals(2, BRIDGING_TABLE.size());
337 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
338 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
339
340 // Add the second location of dual-homed host
341 // Expect: no longer use the pair link
342 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
343 assertEquals(2, ROUTING_TABLE.size());
344 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
345 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
346 assertEquals(2, BRIDGING_TABLE.size());
347 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
348 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
349 }
350
351 @Test
Charles Chan2e2e3402017-06-19 14:00:53 -0700352 public void testHostRemoved() throws Exception {
353 Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700354 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700355
356 // Add a host
357 // Expect: add one routing rule and one bridging rule
358 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700359 assertEquals(1, ROUTING_TABLE.size());
360 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
361 assertEquals(1, BRIDGING_TABLE.size());
362 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700363
364 // Remove the host
365 // Expect: add the routing rule and the bridging rule
Charles Chanf9a52702017-06-16 15:19:24 -0700366 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, subject));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700367 assertEquals(0, ROUTING_TABLE.size());
368 assertEquals(0, BRIDGING_TABLE.size());
Charles Chanf9a52702017-06-16 15:19:24 -0700369 }
370
371 @Test
372 public void testDualHomedHostRemoved() throws Exception {
373 // Add a dual-homed host that has 2 locations
374 // Expect: add two routing rules and two bridging rules
375 Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
376 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
377 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700378 assertEquals(2, ROUTING_TABLE.size());
379 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
380 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
381 assertEquals(2, BRIDGING_TABLE.size());
382 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
383 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700384
385 // Remove a dual-homed host that has 2 locations
386 // Expect: all routing and bridging rules are removed
387 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, subject));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700388 assertEquals(0, ROUTING_TABLE.size());
389 assertEquals(0, BRIDGING_TABLE.size());
Charles Chan2e2e3402017-06-19 14:00:53 -0700390 }
391
392 @Test
393 public void testHostMoved() throws Exception {
394 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700395 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700396 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700397 Sets.newHashSet(HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700398 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700399 Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700400
401 // Add a host
Charles Chan65238242017-06-22 18:03:14 -0700402 // Expect: add one new routing rule, one new bridging rule
Charles Chan2e2e3402017-06-19 14:00:53 -0700403 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700404 assertEquals(1, ROUTING_TABLE.size());
405 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
406 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
407 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())));
408 assertEquals(1, BRIDGING_TABLE.size());
409 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
410 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700411
Charles Chanf9a52702017-06-16 15:19:24 -0700412 // Move the host to CP13, which has different subnet setting
Charles Chan2e2e3402017-06-19 14:00:53 -0700413 // Expect: remove routing rule. Change vlan in bridging rule.
Charles Chanf9a52702017-06-16 15:19:24 -0700414 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700415 assertEquals(0, ROUTING_TABLE.size());
416 assertEquals(1, BRIDGING_TABLE.size());
417 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_NATIVE)));
418 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700419
Charles Chanf9a52702017-06-16 15:19:24 -0700420 // Move the host to CP21, which has same subnet setting
Charles Chan2e2e3402017-06-19 14:00:53 -0700421 // Expect: add a new routing rule. Change vlan in bridging rule.
Charles Chanf9a52702017-06-16 15:19:24 -0700422 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host3));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700423 assertEquals(1, ROUTING_TABLE.size());
424 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
425 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
426 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
427 assertEquals(1, BRIDGING_TABLE.size());
428 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
429 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700430 }
431
432 @Test
433 public void testDualHomedHostMoved() throws Exception {
434 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
435 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
436 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
437 Sets.newHashSet(HOST_LOC12, HOST_LOC22), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
438 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
439 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP13, HOST_IP14), false);
440 Host host4 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
441 Sets.newHashSet(HOST_LOC11, HOST_LOC22), Sets.newHashSet(HOST_IP12, HOST_IP13), false);
442
443 // Add a host with IP11, IP12 and LOC11, LOC21
444 // Expect: 4 routing rules and 2 bridging rules
445 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700446 assertEquals(4, ROUTING_TABLE.size());
447 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
448 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
449 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
450 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
451 assertEquals(2, BRIDGING_TABLE.size());
452 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
453 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanf9a52702017-06-16 15:19:24 -0700454
455 // Move the host to LOC12, LOC22 and keep the IP
456 // Expect: 4 routing rules and 2 bridging rules all at the new location
457 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700458 assertEquals(4, ROUTING_TABLE.size());
459 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
460 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
461 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
462 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
463 assertEquals(2, BRIDGING_TABLE.size());
464 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
465 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanf9a52702017-06-16 15:19:24 -0700466
467 // Move the host to LOC11, LOC21 and change the IP to IP13, IP14 at the same time
468 // Expect: 4 routing rules and 2 bridging rules all at the new location
469 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700470 assertEquals(4, ROUTING_TABLE.size());
471 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())).portNumber);
472 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP14.toIpPrefix())).portNumber);
473 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())).portNumber);
474 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP14.toIpPrefix())).portNumber);
475 assertEquals(2, BRIDGING_TABLE.size());
476 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
477 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chanf9a52702017-06-16 15:19:24 -0700478
479 // Move the host to LOC11, LOC22 and change the IP to IP12, IP13 at the same time
480 // Expect: 4 routing rules and 2 bridging rules all at the new location
481 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host4, host3));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700482 assertEquals(4, ROUTING_TABLE.size());
483 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
484 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())).portNumber);
485 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
486 assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())).portNumber);
487 assertEquals(2, BRIDGING_TABLE.size());
488 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
489 assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan2e2e3402017-06-19 14:00:53 -0700490 }
491
492 @Test
Charles Chan9f08b102017-08-09 16:50:15 -0700493 public void testHostMoveToInvalidLocation() throws Exception {
494 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
495 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
496 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
497 Sets.newHashSet(HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
498
499 // Add a host
500 // Expect: add one new routing rule, one new bridging rule
501 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700502 assertEquals(1, ROUTING_TABLE.size());
503 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
504 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
505 assertEquals(1, BRIDGING_TABLE.size());
506 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
507 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan9f08b102017-08-09 16:50:15 -0700508
509 // Move the host to an invalid location
510 // Expect: Old flow is removed. New flow is not created
511 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700512 assertEquals(0, ROUTING_TABLE.size());
513 assertEquals(0, BRIDGING_TABLE.size());
Charles Chan9f08b102017-08-09 16:50:15 -0700514
515 // Move the host to a valid location
516 // Expect: add one new routing rule, one new bridging rule
517 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700518 assertEquals(1, ROUTING_TABLE.size());
519 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
520 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
521 assertEquals(1, BRIDGING_TABLE.size());
522 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
523 assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan9f08b102017-08-09 16:50:15 -0700524 }
525
526 @Test
527 public void testDualHomedHostMoveToInvalidLocation() throws Exception {
528 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
529 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
530 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
531 Sets.newHashSet(HOST_LOC11, HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
532 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
533 Sets.newHashSet(HOST_LOC61, HOST_LOC51), Sets.newHashSet(HOST_IP11), false);
534
535 // Add a host
536 // Expect: add two new routing rules, two new bridging rules
537 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700538 assertEquals(2, ROUTING_TABLE.size());
539 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
540 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
541 assertEquals(2, BRIDGING_TABLE.size());
542 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
543 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan9f08b102017-08-09 16:50:15 -0700544
545 // Move first host location to an invalid location
546 // Expect: One routing and one bridging flow
547 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700548 assertEquals(1, ROUTING_TABLE.size());
549 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
550 assertEquals(1, BRIDGING_TABLE.size());
551 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan9f08b102017-08-09 16:50:15 -0700552
553 // Move second host location to an invalid location
554 // Expect: No routing or bridging rule
555 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700556 assertEquals(0, ROUTING_TABLE.size());
557 assertEquals(0, BRIDGING_TABLE.size());
Charles Chan9f08b102017-08-09 16:50:15 -0700558
559 // Move second host location back to a valid location
560 // Expect: One routing and one bridging flow
561 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host3));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700562 assertEquals(1, ROUTING_TABLE.size());
563 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
564 assertEquals(1, BRIDGING_TABLE.size());
565 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan9f08b102017-08-09 16:50:15 -0700566
567 // Move first host location back to a valid location
568 // Expect: Two routing and two bridging flow
569 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700570 assertEquals(2, ROUTING_TABLE.size());
571 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
572 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
573 assertEquals(2, BRIDGING_TABLE.size());
574 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
575 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan9f08b102017-08-09 16:50:15 -0700576 }
577
578 @Test
Charles Chan65238242017-06-22 18:03:14 -0700579 public void testDualHomingSingleLocationFail() throws Exception {
580 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
581 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
582 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
583 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
584
585 // Add a host
586 // Expect: add four new routing rules, two new bridging rules
587 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700588 assertEquals(4, ROUTING_TABLE.size());
589 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
590 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
591 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
592 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
593 assertEquals(2, BRIDGING_TABLE.size());
594 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
595 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan65238242017-06-22 18:03:14 -0700596
597 // Host becomes single-homed
598 // Expect: redirect flows from host location to pair link
599 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700600 assertEquals(4, ROUTING_TABLE.size());
601 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
602 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
603 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
604 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
605 assertEquals(2, BRIDGING_TABLE.size());
606 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
607 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan65238242017-06-22 18:03:14 -0700608
609 // Host becomes dual-homed again
610 // Expect: Redirect flows from pair link back to host location
611 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700612 assertEquals(4, ROUTING_TABLE.size());
613 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
614 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
615 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
616 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
617 assertEquals(2, BRIDGING_TABLE.size());
618 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
619 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan65238242017-06-22 18:03:14 -0700620 }
621
622 @Test
623 public void testDualHomingBothLocationFail() throws Exception {
624 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
625 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
626 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
627 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
628
629 // Add a host
630 // Expect: add four new routing rules, two new bridging rules
631 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700632 assertEquals(4, ROUTING_TABLE.size());
633 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
634 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
635 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
636 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
637 assertEquals(2, BRIDGING_TABLE.size());
638 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
639 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan65238242017-06-22 18:03:14 -0700640
641 // Host becomes single-homed
642 // Expect: redirect flows from host location to pair link
643 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700644 assertEquals(4, ROUTING_TABLE.size());
645 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
646 assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
647 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
648 assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
649 assertEquals(2, BRIDGING_TABLE.size());
650 assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
651 assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan65238242017-06-22 18:03:14 -0700652
653 // Host loses both locations
654 // Expect: Remove last location and all previous redirection flows
655 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, host2));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700656 assertEquals(0, ROUTING_TABLE.size());
657 assertEquals(0, BRIDGING_TABLE.size());
Charles Chan65238242017-06-22 18:03:14 -0700658 }
659
660 @Test
Charles Chan2e2e3402017-06-19 14:00:53 -0700661 public void testHostUpdated() throws Exception {
662 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700663 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700664 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700665 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP21), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700666 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700667 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP12), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700668
669 // Add a host
Charles Chanf9a52702017-06-16 15:19:24 -0700670 // Expect: add one new routing rule. Add one new bridging rule.
Charles Chan2e2e3402017-06-19 14:00:53 -0700671 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700672 assertEquals(1, ROUTING_TABLE.size());
673 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
674 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
675 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
676 assertEquals(1, BRIDGING_TABLE.size());
677 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(HOST_LOC11.deviceId(), HOST_MAC,
678 INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700679
680 // Update the host IP to same subnet
681 // Expect: update routing rule with new IP. No change to bridging rule.
682 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700683 assertEquals(1, ROUTING_TABLE.size());
684 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
685 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
686 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
687 assertEquals(1, BRIDGING_TABLE.size());
688 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700689
690 // Update the host IP to different subnet
691 // Expect: Remove routing rule. No change to bridging rule.
692 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host3));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700693 assertEquals(0, ROUTING_TABLE.size());
694 assertEquals(1, BRIDGING_TABLE.size());
695 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700696 }
697
698 @Test
699 public void testDualHomedHostUpdated() throws Exception {
700 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
701 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
702 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
703 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP21), false);
704 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
705 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP13, HOST_IP14), false);
706
707 // Add a dual-homed host with two locations and two IPs
708 // Expect: add four new routing rules. Add two new bridging rules
709 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700710 assertEquals(4, ROUTING_TABLE.size());
711 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
712 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
713 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
714 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
715 assertEquals(2, BRIDGING_TABLE.size());
716 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
717 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700718
719 // Update both host IPs
720 // Expect: update routing rules with new IP. No change to bridging rule.
721 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host1));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700722 assertEquals(4, ROUTING_TABLE.size());
723 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
724 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
725 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())));
726 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP14.toIpPrefix())));
727 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
728 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
729 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())));
730 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP14.toIpPrefix())));
731 assertEquals(2, BRIDGING_TABLE.size());
732 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
733 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700734
735 // Update one of the host IP to different subnet
736 // Expect: update routing rule with new IP. No change to bridging rule.
737 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host3));
Charles Chan1a3b02a2017-08-18 17:11:34 -0700738 assertEquals(2, ROUTING_TABLE.size());
739 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
740 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
741 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
742 assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
743 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP21.toIpPrefix())));
744 assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
745 assertEquals(2, BRIDGING_TABLE.size());
746 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
747 assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chanf9a52702017-06-16 15:19:24 -0700748 }
749
750 @Test
751 public void testBridgingFwdObjBuilder() throws Exception {
752 assertNotNull(hostHandler.bridgingFwdObjBuilder(DEV2, HOST_MAC, HOST_VLAN_UNTAGGED, P1, false));
753 assertNull(hostHandler.bridgingFwdObjBuilder(DEV2, HOST_MAC, HOST_VLAN_UNTAGGED, P3, false));
Charles Chan2e2e3402017-06-19 14:00:53 -0700754 }
Ray Milkeyfacf2862017-08-03 11:58:29 -0700755}