blob: ca3378ce5b93c7130869a36dc0fe75db78392ebb [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;
30import org.onosproject.core.DefaultApplicationId;
Ray Milkeyfacf2862017-08-03 11:58:29 -070031import org.onosproject.net.intf.Interface;
32import org.onosproject.net.intf.InterfaceServiceAdapter;
Charles Chan2e2e3402017-06-19 14:00:53 -070033import org.onosproject.net.ConnectPoint;
34import org.onosproject.net.DefaultHost;
35import org.onosproject.net.DeviceId;
36import org.onosproject.net.Host;
37import org.onosproject.net.HostId;
38import org.onosproject.net.HostLocation;
39import org.onosproject.net.PortNumber;
Charles Chan65238242017-06-22 18:03:14 -070040import org.onosproject.net.config.Config;
41import org.onosproject.net.config.ConfigApplyDelegate;
Charles Chan2e2e3402017-06-19 14:00:53 -070042import org.onosproject.net.config.NetworkConfigRegistryAdapter;
43import org.onosproject.net.flow.TrafficSelector;
44import org.onosproject.net.flow.TrafficTreatment;
45import org.onosproject.net.flow.criteria.Criterion;
46import org.onosproject.net.flow.criteria.EthCriterion;
47import org.onosproject.net.flow.criteria.VlanIdCriterion;
48import org.onosproject.net.flow.instructions.Instruction;
49import org.onosproject.net.flow.instructions.Instructions;
50import org.onosproject.net.flow.instructions.L2ModificationInstruction;
51import org.onosproject.net.flowobjective.FlowObjectiveServiceAdapter;
52import org.onosproject.net.flowobjective.ForwardingObjective;
53import org.onosproject.net.flowobjective.Objective;
54import org.onosproject.net.host.HostEvent;
Charles Chanf9a52702017-06-16 15:19:24 -070055import org.onosproject.net.host.HostServiceAdapter;
Charles Chan2e2e3402017-06-19 14:00:53 -070056import org.onosproject.net.host.InterfaceIpAddress;
57import org.onosproject.net.provider.ProviderId;
58import org.onosproject.segmentrouting.config.DeviceConfiguration;
Charles Chan65238242017-06-22 18:03:14 -070059import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
Charles Chan2e2e3402017-06-19 14:00:53 -070060
61import java.util.Map;
62import java.util.Objects;
63import java.util.Set;
64import java.util.concurrent.atomic.AtomicInteger;
65
66import static org.junit.Assert.*;
67
68/**
69 * Unit test for {@link HostHandler}.
70 */
71public class HostHandlerTest {
72 private SegmentRoutingManager srManager;
73 private HostHandler hostHandler;
74
75 // Mocked routing and bridging tables
76 private Map<BridingTableKey, BridingTableValue> bridgingTable = Maps.newConcurrentMap();
77 private Map<RoutingTableKey, RoutingTableValue> routingTable = Maps.newConcurrentMap();
78 // Mocked Next Id
79 private Map<Integer, TrafficTreatment> nextTable = Maps.newConcurrentMap();
80 private AtomicInteger atomicNextId = new AtomicInteger();
81
Charles Chanf9a52702017-06-16 15:19:24 -070082 // Host Mac, VLAN
Charles Chan2e2e3402017-06-19 14:00:53 -070083 private static final ProviderId PROVIDER_ID = ProviderId.NONE;
84 private static final MacAddress HOST_MAC = MacAddress.valueOf("00:00:00:00:00:01");
85 private static final VlanId HOST_VLAN_UNTAGGED = VlanId.NONE;
86 private static final HostId HOST_ID_UNTAGGED = HostId.hostId(HOST_MAC, HOST_VLAN_UNTAGGED);
87 private static final VlanId HOST_VLAN_TAGGED = VlanId.vlanId((short) 20);
88 private static final HostId HOST_ID_TAGGED = HostId.hostId(HOST_MAC, HOST_VLAN_TAGGED);
Charles Chanf9a52702017-06-16 15:19:24 -070089 // Host IP
90 private static final IpAddress HOST_IP11 = IpAddress.valueOf("10.0.1.1");
91 private static final IpAddress HOST_IP21 = IpAddress.valueOf("10.0.2.1");
92 private static final IpAddress HOST_IP12 = IpAddress.valueOf("10.0.1.2");
93 private static final IpAddress HOST_IP13 = IpAddress.valueOf("10.0.1.3");
94 private static final IpAddress HOST_IP14 = IpAddress.valueOf("10.0.1.4");
95 // Device
96 private static final DeviceId DEV1 = DeviceId.deviceId("of:0000000000000001");
97 private static final DeviceId DEV2 = DeviceId.deviceId("of:0000000000000002");
Charles Chan65238242017-06-22 18:03:14 -070098 private static final DeviceId DEV3 = DeviceId.deviceId("of:000000000000003");
99 private static final DeviceId DEV4 = DeviceId.deviceId("of:000000000000004");
Charles Chanf9a52702017-06-16 15:19:24 -0700100 // Port
101 private static final PortNumber P1 = PortNumber.portNumber(1);
102 private static final PortNumber P2 = PortNumber.portNumber(2);
103 private static final PortNumber P3 = PortNumber.portNumber(3);
Charles Chan65238242017-06-22 18:03:14 -0700104 private static final PortNumber P9 = PortNumber.portNumber(9);
Charles Chanf9a52702017-06-16 15:19:24 -0700105 // Connect Point
106 private static final ConnectPoint CP11 = new ConnectPoint(DEV1, P1);
107 private static final HostLocation HOST_LOC11 = new HostLocation(CP11, 0);
108 private static final ConnectPoint CP12 = new ConnectPoint(DEV1, P2);
109 private static final HostLocation HOST_LOC12 = new HostLocation(CP12, 0);
110 private static final ConnectPoint CP13 = new ConnectPoint(DEV1, P3);
111 private static final HostLocation HOST_LOC13 = new HostLocation(CP13, 0);
112 private static final ConnectPoint CP21 = new ConnectPoint(DEV2, P1);
113 private static final HostLocation HOST_LOC21 = new HostLocation(CP21, 0);
114 private static final ConnectPoint CP22 = new ConnectPoint(DEV2, P2);
115 private static final HostLocation HOST_LOC22 = new HostLocation(CP22, 0);
Charles Chan65238242017-06-22 18:03:14 -0700116 // Connect Point for dual-homed host failover
117 private static final ConnectPoint CP31 = new ConnectPoint(DEV3, P1);
118 private static final HostLocation HOST_LOC31 = new HostLocation(CP31, 0);
119 private static final ConnectPoint CP41 = new ConnectPoint(DEV4, P1);
120 private static final HostLocation HOST_LOC41 = new HostLocation(CP41, 0);
121 private static final ConnectPoint CP39 = new ConnectPoint(DEV3, P9);
122 private static final ConnectPoint CP49 = new ConnectPoint(DEV4, P9);
Charles Chanf9a52702017-06-16 15:19:24 -0700123 // Interface VLAN
Charles Chan2e2e3402017-06-19 14:00:53 -0700124 private static final VlanId INTF_VLAN_UNTAGGED = VlanId.vlanId((short) 10);
Charles Chan2e2e3402017-06-19 14:00:53 -0700125 private static final Set<VlanId> INTF_VLAN_TAGGED = Sets.newHashSet(VlanId.vlanId((short) 20));
126 private static final VlanId INTF_VLAN_NATIVE = VlanId.vlanId((short) 30);
Charles Chan65238242017-06-22 18:03:14 -0700127 private static final Set<VlanId> INTF_VLAN_PAIR = Sets.newHashSet(VlanId.vlanId((short) 10),
128 VlanId.vlanId((short) 20), VlanId.vlanId((short) 30));
Charles Chanf9a52702017-06-16 15:19:24 -0700129 // Interface subnet
130 private static final IpPrefix INTF_PREFIX1 = IpPrefix.valueOf("10.0.1.254/24");
131 private static final IpPrefix INTF_PREFIX2 = IpPrefix.valueOf("10.0.2.254/24");
132 private static final InterfaceIpAddress INTF_IP1 =
133 new InterfaceIpAddress(INTF_PREFIX1.address(), INTF_PREFIX1);
134 private static final InterfaceIpAddress INTF_IP2 =
135 new InterfaceIpAddress(INTF_PREFIX2.address(), INTF_PREFIX2);
136 // Host
137 private static final Host HOST1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC,
138 HOST_VLAN_UNTAGGED, Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11),
139 false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700140
141 @Before
142 public void setUp() throws Exception {
143 srManager = new MockSegmentRoutingManager();
144 srManager.cfgService = new NetworkConfigRegistryAdapter();
145 srManager.deviceConfiguration = new DeviceConfiguration(srManager);
146 srManager.flowObjectiveService = new MockFlowObjectiveService();
147 srManager.routingRulePopulator = new MockRoutingRulePopulator();
148 srManager.interfaceService = new MockInterfaceService();
Charles Chanf9a52702017-06-16 15:19:24 -0700149 srManager.hostService = new MockHostService();
Charles Chan65238242017-06-22 18:03:14 -0700150 srManager.cfgService = new MockNetworkConfigRegistry();
Charles Chan2e2e3402017-06-19 14:00:53 -0700151
152 hostHandler = new HostHandler(srManager);
153
154 routingTable.clear();
155 bridgingTable.clear();
156 }
157
158 @Test
159 public void init() throws Exception {
Charles Chanf9a52702017-06-16 15:19:24 -0700160 hostHandler.init(DEV1);
161 assertEquals(1, routingTable.size());
162 assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
163 assertEquals(1, bridgingTable.size());
164 assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
165
166 hostHandler.init(DEV2);
167 assertEquals(2, routingTable.size());
168 assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
169 assertNotNull(routingTable.get(new RoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
170 assertEquals(2, bridgingTable.size());
171 assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
172 assertNotNull(bridgingTable.get(new BridingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
173 }
174
175 @Test(expected = IllegalArgumentException.class)
176 public void testHostAddedAtWrongLocation() throws Exception {
177 hostHandler.processHostAddedAtLocation(HOST1, HOST_LOC13);
178 }
179
180
181 @Test()
182 public void testHostAddedAtCorrectLocation() throws Exception {
183 hostHandler.processHostAddedAtLocation(HOST1, HOST_LOC11);
184 assertEquals(1, routingTable.size());
185 assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
186 assertEquals(1, bridgingTable.size());
187 assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700188 }
189
190 @Test
191 public void testHostAdded() throws Exception {
192 Host subject;
193
194 // Untagged host discovered on untagged port
195 // Expect: add one routing rule and one bridging rule
196 subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700197 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700198 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
199 assertEquals(1, routingTable.size());
Charles Chanf9a52702017-06-16 15:19:24 -0700200 assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
Charles Chan2e2e3402017-06-19 14:00:53 -0700201 assertEquals(1, bridgingTable.size());
Charles Chanf9a52702017-06-16 15:19:24 -0700202 assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700203
204 // Untagged host discovered on tagged/native port
205 // Expect: add one routing rule and one bridging rule
206 subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700207 Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP21), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700208 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
209 assertEquals(2, routingTable.size());
Charles Chanf9a52702017-06-16 15:19:24 -0700210 assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
Charles Chan2e2e3402017-06-19 14:00:53 -0700211 assertEquals(2, bridgingTable.size());
Charles Chanf9a52702017-06-16 15:19:24 -0700212 assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_NATIVE)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700213
214 // Tagged host discovered on untagged port
215 // Expect: ignore the host. No rule is added.
216 subject = new DefaultHost(PROVIDER_ID, HOST_ID_TAGGED, HOST_MAC, HOST_VLAN_TAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700217 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700218 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
219 assertEquals(2, routingTable.size());
220 assertEquals(2, bridgingTable.size());
221
222 // Tagged host discovered on tagged port with the same IP
223 // Expect: update existing route, add one bridging rule
224 subject = new DefaultHost(PROVIDER_ID, HOST_ID_TAGGED, HOST_MAC, HOST_VLAN_TAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700225 Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP21), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700226 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
227 assertEquals(2, routingTable.size());
Charles Chanf9a52702017-06-16 15:19:24 -0700228 assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
229 assertEquals(HOST_VLAN_TAGGED, routingTable.get(new RoutingTableKey(HOST_LOC13.deviceId(),
230 HOST_IP21.toIpPrefix())).vlanId);
Charles Chan2e2e3402017-06-19 14:00:53 -0700231 assertEquals(3, bridgingTable.size());
Charles Chanf9a52702017-06-16 15:19:24 -0700232 assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, HOST_VLAN_TAGGED)));
233 }
234
235 @Test
236 public void testDualHomedHostAdded() throws Exception {
237 // Add a dual-homed host that has 2 locations
238 // Expect: add two routing rules and two bridging rules
239 Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
240 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
241 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
242 assertEquals(2, routingTable.size());
243 assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
244 assertNotNull(routingTable.get(new RoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
245 assertEquals(2, bridgingTable.size());
246 assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
247 assertNotNull(bridgingTable.get(new BridingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700248 }
249
250 @Test
251 public void testHostRemoved() throws Exception {
252 Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700253 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700254
255 // Add a host
256 // Expect: add one routing rule and one bridging rule
257 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
258 assertEquals(1, routingTable.size());
Charles Chanf9a52702017-06-16 15:19:24 -0700259 assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
Charles Chan2e2e3402017-06-19 14:00:53 -0700260 assertEquals(1, bridgingTable.size());
Charles Chanf9a52702017-06-16 15:19:24 -0700261 assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700262
263 // Remove the host
264 // Expect: add the routing rule and the bridging rule
Charles Chanf9a52702017-06-16 15:19:24 -0700265 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, subject));
Charles Chan2e2e3402017-06-19 14:00:53 -0700266 assertEquals(0, routingTable.size());
Charles Chan2e2e3402017-06-19 14:00:53 -0700267 assertEquals(0, bridgingTable.size());
Charles Chanf9a52702017-06-16 15:19:24 -0700268 }
269
270 @Test
271 public void testDualHomedHostRemoved() throws Exception {
272 // Add a dual-homed host that has 2 locations
273 // Expect: add two routing rules and two bridging rules
274 Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
275 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
276 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
277 assertEquals(2, routingTable.size());
278 assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
279 assertNotNull(routingTable.get(new RoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
280 assertEquals(2, bridgingTable.size());
281 assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
282 assertNotNull(bridgingTable.get(new BridingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
283
284 // Remove a dual-homed host that has 2 locations
285 // Expect: all routing and bridging rules are removed
286 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, subject));
287 assertEquals(0, routingTable.size());
288 assertEquals(0, bridgingTable.size());
Charles Chan2e2e3402017-06-19 14:00:53 -0700289 }
290
291 @Test
292 public void testHostMoved() throws Exception {
293 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700294 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700295 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700296 Sets.newHashSet(HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700297 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700298 Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700299
300 // Add a host
Charles Chan65238242017-06-22 18:03:14 -0700301 // Expect: add one new routing rule, one new bridging rule
Charles Chan2e2e3402017-06-19 14:00:53 -0700302 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
303 assertEquals(1, routingTable.size());
Charles Chanf9a52702017-06-16 15:19:24 -0700304 assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
305 assertNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
306 assertNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP13.toIpPrefix())));
Charles Chan2e2e3402017-06-19 14:00:53 -0700307 assertEquals(1, bridgingTable.size());
Charles Chanf9a52702017-06-16 15:19:24 -0700308 assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
309 assertNull(bridgingTable.get(new BridingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700310
Charles Chanf9a52702017-06-16 15:19:24 -0700311 // Move the host to CP13, which has different subnet setting
Charles Chan2e2e3402017-06-19 14:00:53 -0700312 // Expect: remove routing rule. Change vlan in bridging rule.
Charles Chanf9a52702017-06-16 15:19:24 -0700313 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host1));
Charles Chan2e2e3402017-06-19 14:00:53 -0700314 assertEquals(0, routingTable.size());
Charles Chan2e2e3402017-06-19 14:00:53 -0700315 assertEquals(1, bridgingTable.size());
Charles Chanf9a52702017-06-16 15:19:24 -0700316 assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_NATIVE)));
317 assertNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700318
Charles Chanf9a52702017-06-16 15:19:24 -0700319 // Move the host to CP21, which has same subnet setting
Charles Chan2e2e3402017-06-19 14:00:53 -0700320 // Expect: add a new routing rule. Change vlan in bridging rule.
Charles Chanf9a52702017-06-16 15:19:24 -0700321 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host3));
Charles Chan2e2e3402017-06-19 14:00:53 -0700322 assertEquals(1, routingTable.size());
Charles Chanf9a52702017-06-16 15:19:24 -0700323 assertNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
324 assertNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
325 assertNotNull(routingTable.get(new RoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
Charles Chan2e2e3402017-06-19 14:00:53 -0700326 assertEquals(1, bridgingTable.size());
Charles Chanf9a52702017-06-16 15:19:24 -0700327 assertNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
328 assertNotNull(bridgingTable.get(new BridingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
329 }
330
331 @Test
332 public void testDualHomedHostMoved() throws Exception {
333 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
334 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
335 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
336 Sets.newHashSet(HOST_LOC12, HOST_LOC22), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
337 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
338 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP13, HOST_IP14), false);
339 Host host4 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
340 Sets.newHashSet(HOST_LOC11, HOST_LOC22), Sets.newHashSet(HOST_IP12, HOST_IP13), false);
341
342 // Add a host with IP11, IP12 and LOC11, LOC21
343 // Expect: 4 routing rules and 2 bridging rules
344 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
345 assertEquals(4, routingTable.size());
346 assertEquals(P1, routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
347 assertEquals(P1, routingTable.get(new RoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
348 assertEquals(P1, routingTable.get(new RoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
349 assertEquals(P1, routingTable.get(new RoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
350 assertEquals(2, bridgingTable.size());
351 assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
352 assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
353
354 // Move the host to LOC12, LOC22 and keep the IP
355 // Expect: 4 routing rules and 2 bridging rules all at the new location
356 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
357 assertEquals(4, routingTable.size());
358 assertEquals(P2, routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
359 assertEquals(P2, routingTable.get(new RoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
360 assertEquals(P2, routingTable.get(new RoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
361 assertEquals(P2, routingTable.get(new RoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
362 assertEquals(2, bridgingTable.size());
363 assertEquals(P2, bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
364 assertEquals(P2, bridgingTable.get(new BridingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
365
366 // Move the host to LOC11, LOC21 and change the IP to IP13, IP14 at the same time
367 // Expect: 4 routing rules and 2 bridging rules all at the new location
368 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
369 assertEquals(4, routingTable.size());
370 assertEquals(P1, routingTable.get(new RoutingTableKey(DEV1, HOST_IP13.toIpPrefix())).portNumber);
371 assertEquals(P1, routingTable.get(new RoutingTableKey(DEV1, HOST_IP14.toIpPrefix())).portNumber);
372 assertEquals(P1, routingTable.get(new RoutingTableKey(DEV2, HOST_IP13.toIpPrefix())).portNumber);
373 assertEquals(P1, routingTable.get(new RoutingTableKey(DEV2, HOST_IP14.toIpPrefix())).portNumber);
374 assertEquals(2, bridgingTable.size());
375 assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
376 assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
377
378 // Move the host to LOC11, LOC22 and change the IP to IP12, IP13 at the same time
379 // Expect: 4 routing rules and 2 bridging rules all at the new location
380 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host4, host3));
381 assertEquals(4, routingTable.size());
382 assertEquals(P1, routingTable.get(new RoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
383 assertEquals(P1, routingTable.get(new RoutingTableKey(DEV1, HOST_IP13.toIpPrefix())).portNumber);
384 assertEquals(P2, routingTable.get(new RoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
385 assertEquals(P2, routingTable.get(new RoutingTableKey(DEV2, HOST_IP13.toIpPrefix())).portNumber);
386 assertEquals(2, bridgingTable.size());
387 assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
388 assertEquals(P2, bridgingTable.get(new BridingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
Charles Chan2e2e3402017-06-19 14:00:53 -0700389 }
390
391 @Test
Charles Chan65238242017-06-22 18:03:14 -0700392 public void testDualHomingSingleLocationFail() throws Exception {
393 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
394 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
395 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
396 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
397
398 // Add a host
399 // Expect: add four new routing rules, two new bridging rules
400 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
401 assertEquals(4, routingTable.size());
402 assertEquals(P1, routingTable.get(new RoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
403 assertEquals(P1, routingTable.get(new RoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
404 assertEquals(P1, routingTable.get(new RoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
405 assertEquals(P1, routingTable.get(new RoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
406 assertEquals(2, bridgingTable.size());
407 assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
408 assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
409
410 // Host becomes single-homed
411 // Expect: redirect flows from host location to pair link
412 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
413 assertEquals(4, routingTable.size());
414 assertEquals(P1, routingTable.get(new RoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
415 assertEquals(P1, routingTable.get(new RoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
416 assertEquals(P9, routingTable.get(new RoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
417 assertEquals(P9, routingTable.get(new RoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
418 assertEquals(2, bridgingTable.size());
419 assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
420 assertEquals(P9, bridgingTable.get(new BridingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
421
422 // Host becomes dual-homed again
423 // Expect: Redirect flows from pair link back to host location
424 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
425 assertEquals(4, routingTable.size());
426 assertEquals(P1, routingTable.get(new RoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
427 assertEquals(P1, routingTable.get(new RoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
428 assertEquals(P1, routingTable.get(new RoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
429 assertEquals(P1, routingTable.get(new RoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
430 assertEquals(2, bridgingTable.size());
431 assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
432 assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
433 }
434
435 @Test
436 public void testDualHomingBothLocationFail() throws Exception {
437 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
438 Sets.newHashSet(HOST_LOC31, HOST_LOC41), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
439 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
440 Sets.newHashSet(HOST_LOC31), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
441
442 // Add a host
443 // Expect: add four new routing rules, two new bridging rules
444 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
445 assertEquals(4, routingTable.size());
446 assertEquals(P1, routingTable.get(new RoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
447 assertEquals(P1, routingTable.get(new RoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
448 assertEquals(P1, routingTable.get(new RoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
449 assertEquals(P1, routingTable.get(new RoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
450 assertEquals(2, bridgingTable.size());
451 assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
452 assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
453
454 // Host becomes single-homed
455 // Expect: redirect flows from host location to pair link
456 hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
457 assertEquals(4, routingTable.size());
458 assertEquals(P1, routingTable.get(new RoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
459 assertEquals(P1, routingTable.get(new RoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
460 assertEquals(P9, routingTable.get(new RoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
461 assertEquals(P9, routingTable.get(new RoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
462 assertEquals(2, bridgingTable.size());
463 assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
464 assertEquals(P9, bridgingTable.get(new BridingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
465
466 // Host loses both locations
467 // Expect: Remove last location and all previous redirection flows
468 hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, host2));
469 assertEquals(0, routingTable.size());
470 assertEquals(0, bridgingTable.size());
471 }
472
473 @Test
Charles Chan2e2e3402017-06-19 14:00:53 -0700474 public void testHostUpdated() throws Exception {
475 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700476 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700477 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700478 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP21), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700479 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
Charles Chanf9a52702017-06-16 15:19:24 -0700480 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP12), false);
Charles Chan2e2e3402017-06-19 14:00:53 -0700481
482 // Add a host
Charles Chanf9a52702017-06-16 15:19:24 -0700483 // Expect: add one new routing rule. Add one new bridging rule.
Charles Chan2e2e3402017-06-19 14:00:53 -0700484 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
485 assertEquals(1, routingTable.size());
Charles Chanf9a52702017-06-16 15:19:24 -0700486 assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
487 assertNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
488 assertNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
Charles Chan2e2e3402017-06-19 14:00:53 -0700489 assertEquals(1, bridgingTable.size());
Charles Chanf9a52702017-06-16 15:19:24 -0700490 assertNotNull(bridgingTable.get(new BridingTableKey(HOST_LOC11.deviceId(), HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700491
492 // Update the host IP to same subnet
493 // Expect: update routing rule with new IP. No change to bridging rule.
494 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host1));
495 assertEquals(1, routingTable.size());
Charles Chanf9a52702017-06-16 15:19:24 -0700496 assertNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
497 assertNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
498 assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
Charles Chan2e2e3402017-06-19 14:00:53 -0700499 assertEquals(1, bridgingTable.size());
Charles Chanf9a52702017-06-16 15:19:24 -0700500 assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
Charles Chan2e2e3402017-06-19 14:00:53 -0700501
502 // Update the host IP to different subnet
503 // Expect: Remove routing rule. No change to bridging rule.
504 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host3));
505 assertEquals(0, routingTable.size());
Charles Chan2e2e3402017-06-19 14:00:53 -0700506 assertEquals(1, bridgingTable.size());
Charles Chanf9a52702017-06-16 15:19:24 -0700507 assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
508 }
509
510 @Test
511 public void testDualHomedHostUpdated() throws Exception {
512 Host host1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
513 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP12), false);
514 Host host2 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
515 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11, HOST_IP21), false);
516 Host host3 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
517 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP13, HOST_IP14), false);
518
519 // Add a dual-homed host with two locations and two IPs
520 // Expect: add four new routing rules. Add two new bridging rules
521 hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
522 assertEquals(4, routingTable.size());
523 assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
524 assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
525 assertNotNull(routingTable.get(new RoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
526 assertNotNull(routingTable.get(new RoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
527 assertEquals(2, bridgingTable.size());
528 assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
529 assertNotNull(bridgingTable.get(new BridingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
530
531 // Update both host IPs
532 // Expect: update routing rules with new IP. No change to bridging rule.
533 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host1));
534 assertEquals(4, routingTable.size());
535 assertNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
536 assertNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
537 assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP13.toIpPrefix())));
538 assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP14.toIpPrefix())));
539 assertNull(routingTable.get(new RoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
540 assertNull(routingTable.get(new RoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
541 assertNotNull(routingTable.get(new RoutingTableKey(DEV2, HOST_IP13.toIpPrefix())));
542 assertNotNull(routingTable.get(new RoutingTableKey(DEV2, HOST_IP14.toIpPrefix())));
543 assertEquals(2, bridgingTable.size());
544 assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
545 assertNotNull(bridgingTable.get(new BridingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
546
547 // Update one of the host IP to different subnet
548 // Expect: update routing rule with new IP. No change to bridging rule.
549 hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host3));
550 assertEquals(2, routingTable.size());
551 assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
552 assertNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
553 assertNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
554 assertNotNull(routingTable.get(new RoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
555 assertNull(routingTable.get(new RoutingTableKey(DEV2, HOST_IP21.toIpPrefix())));
556 assertNull(routingTable.get(new RoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
557 assertEquals(2, bridgingTable.size());
558 assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
559 assertNotNull(bridgingTable.get(new BridingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
560 }
561
562 @Test
563 public void testBridgingFwdObjBuilder() throws Exception {
564 assertNotNull(hostHandler.bridgingFwdObjBuilder(DEV2, HOST_MAC, HOST_VLAN_UNTAGGED, P1, false));
565 assertNull(hostHandler.bridgingFwdObjBuilder(DEV2, HOST_MAC, HOST_VLAN_UNTAGGED, P3, false));
Charles Chan2e2e3402017-06-19 14:00:53 -0700566 }
567
568 class MockSegmentRoutingManager extends SegmentRoutingManager {
569 MockSegmentRoutingManager() {
570 appId = new DefaultApplicationId(1, SegmentRoutingManager.APP_NAME);
571 }
572
573 @Override
574 public int getPortNextObjectiveId(DeviceId deviceId, PortNumber portNum,
575 TrafficTreatment treatment,
576 TrafficSelector meta,
577 boolean createIfMissing) {
578 int nextId = atomicNextId.incrementAndGet();
579 nextTable.put(nextId, treatment);
580 return nextId;
581 }
582 }
583
584 class MockInterfaceService extends InterfaceServiceAdapter {
585 @Override
586 public Set<Interface> getInterfacesByPort(ConnectPoint cp) {
587 Interface intf = null;
588
Charles Chanf9a52702017-06-16 15:19:24 -0700589 if (CP11.equals(cp)) {
590 intf = new Interface(null, CP11, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
Charles Chan2e2e3402017-06-19 14:00:53 -0700591 INTF_VLAN_UNTAGGED, null, null);
Charles Chanf9a52702017-06-16 15:19:24 -0700592 } else if (CP12.equals(cp)) {
593 intf = new Interface(null, CP12, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
594 INTF_VLAN_UNTAGGED, null, null);
595 } else if (CP13.equals(cp)) {
596 intf = new Interface(null, CP13, Lists.newArrayList(INTF_IP2), MacAddress.NONE, null,
Charles Chan2e2e3402017-06-19 14:00:53 -0700597 null, INTF_VLAN_TAGGED, INTF_VLAN_NATIVE);
Charles Chanf9a52702017-06-16 15:19:24 -0700598 } else if (CP21.equals(cp)) {
599 intf = new Interface(null, CP21, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
600 INTF_VLAN_UNTAGGED, null, null);
601 } else if (CP22.equals(cp)) {
602 intf = new Interface(null, CP22, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
Charles Chan2e2e3402017-06-19 14:00:53 -0700603 INTF_VLAN_UNTAGGED, null, null);
Charles Chan65238242017-06-22 18:03:14 -0700604 } else if (CP31.equals(cp)) {
605 intf = new Interface(null, CP31, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
606 INTF_VLAN_UNTAGGED, null, null);
607 } else if (CP39.equals(cp)) {
608 intf = new Interface(null, CP39, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
609 null, INTF_VLAN_PAIR, null);
610 } else if (CP41.equals(cp)) {
611 intf = new Interface(null, CP41, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
612 INTF_VLAN_UNTAGGED, null, null);
613 } else if (CP49.equals(cp)) {
614 intf = new Interface(null, CP49, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
615 null, INTF_VLAN_PAIR, null);
Charles Chan2e2e3402017-06-19 14:00:53 -0700616 }
Charles Chan2e2e3402017-06-19 14:00:53 -0700617 return Objects.nonNull(intf) ? Sets.newHashSet(intf) : Sets.newHashSet();
618 }
619 }
620
Charles Chan65238242017-06-22 18:03:14 -0700621 class MockNetworkConfigRegistry extends NetworkConfigRegistryAdapter {
622 @Override
623 public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
624 if (subject instanceof DeviceId) {
625 DeviceId deviceId = (DeviceId) subject;
626 ObjectMapper mapper = new ObjectMapper();
627 ConfigApplyDelegate delegate = new MockCfgDelegate();
628 JsonNode emptyTree = new ObjectMapper().createObjectNode();
629
630 SegmentRoutingDeviceConfig config = new SegmentRoutingDeviceConfig();
631 config.init(deviceId, "host-handler-test", emptyTree, mapper, delegate);
632 config.setPairDeviceId(subject.equals(DEV3) ? DEV4 : DEV3)
633 .setPairLocalPort(P9);
634
635 return (C) config;
636 } else {
637 return null;
638 }
639 }
640 }
641
642 class MockCfgDelegate implements ConfigApplyDelegate {
643 @Override
644 public void onApply(@SuppressWarnings("rawtypes") Config config) {
645 config.apply();
646 }
647 }
648
Charles Chan2e2e3402017-06-19 14:00:53 -0700649 class MockFlowObjectiveService extends FlowObjectiveServiceAdapter {
650 @Override
651 public void forward(DeviceId deviceId, ForwardingObjective forwardingObjective) {
652 TrafficSelector selector = forwardingObjective.selector();
653 TrafficTreatment treatment = nextTable.get(forwardingObjective.nextId());
654 MacAddress macAddress = ((EthCriterion) selector.getCriterion(Criterion.Type.ETH_DST)).mac();
655 VlanId vlanId = ((VlanIdCriterion) selector.getCriterion(Criterion.Type.VLAN_VID)).vlanId();
656
657 boolean popVlan = treatment.allInstructions().stream()
658 .filter(instruction -> instruction.type().equals(Instruction.Type.L2MODIFICATION))
659 .anyMatch(instruction -> ((L2ModificationInstruction) instruction).subtype()
660 .equals(L2ModificationInstruction.L2SubType.VLAN_POP));
661 PortNumber portNumber = treatment.allInstructions().stream()
662 .filter(instruction -> instruction.type().equals(Instruction.Type.OUTPUT))
663 .map(instruction -> ((Instructions.OutputInstruction) instruction).port()).findFirst().orElse(null);
664 if (portNumber == null) {
665 throw new IllegalArgumentException();
666 }
667
668 Objective.Operation op = forwardingObjective.op();
669
670 BridingTableKey btKey = new BridingTableKey(deviceId, macAddress, vlanId);
671 BridingTableValue btValue = new BridingTableValue(popVlan, portNumber);
672
673 if (op.equals(Objective.Operation.ADD)) {
674 bridgingTable.put(btKey, btValue);
675 } else if (op.equals(Objective.Operation.REMOVE)) {
676 bridgingTable.remove(btKey, btValue);
677 } else {
678 throw new IllegalArgumentException();
679 }
680 }
681 }
682
Charles Chanf9a52702017-06-16 15:19:24 -0700683 class MockHostService extends HostServiceAdapter {
684 @Override
685 public Set<Host> getHosts() {
686 return Sets.newHashSet(HOST1);
687 }
688 }
689
Charles Chan2e2e3402017-06-19 14:00:53 -0700690 class MockRoutingRulePopulator extends RoutingRulePopulator {
691 MockRoutingRulePopulator() {
692 super(srManager);
693 }
694
695 @Override
696 public void populateRoute(DeviceId deviceId, IpPrefix prefix,
697 MacAddress hostMac, VlanId hostVlanId, PortNumber outPort) {
698 RoutingTableKey rtKey = new RoutingTableKey(deviceId, prefix);
699 RoutingTableValue rtValue = new RoutingTableValue(outPort, hostMac, hostVlanId);
700 routingTable.put(rtKey, rtValue);
701 }
702
703 @Override
704 public void revokeRoute(DeviceId deviceId, IpPrefix prefix,
705 MacAddress hostMac, VlanId hostVlanId, PortNumber outPort) {
706 RoutingTableKey rtKey = new RoutingTableKey(deviceId, prefix);
707 RoutingTableValue rtValue = new RoutingTableValue(outPort, hostMac, hostVlanId);
708 routingTable.remove(rtKey, rtValue);
709 }
710 }
711
712 class BridingTableKey {
713 DeviceId deviceId;
714 MacAddress macAddress;
715 VlanId vlanId;
716
717 BridingTableKey(DeviceId deviceId, MacAddress macAddress, VlanId vlanId) {
718 this.deviceId = deviceId;
719 this.macAddress = macAddress;
720 this.vlanId = vlanId;
721 }
722
723 @Override
724 public boolean equals(final Object obj) {
725 if (this == obj) {
726 return true;
727 }
728 if (!(obj instanceof BridingTableKey)) {
729 return false;
730 }
731 final BridingTableKey other = (BridingTableKey) obj;
732 return Objects.equals(this.macAddress, other.macAddress) &&
733 Objects.equals(this.deviceId, other.deviceId) &&
734 Objects.equals(this.vlanId, other.vlanId);
735 }
736
737 @Override
738 public int hashCode() {
739 return Objects.hash(macAddress, vlanId);
740 }
741 }
742
743 class BridingTableValue {
744 boolean popVlan;
745 PortNumber portNumber;
746
747 BridingTableValue(boolean popVlan, PortNumber portNumber) {
748 this.popVlan = popVlan;
749 this.portNumber = portNumber;
750 }
751
752 @Override
753 public boolean equals(final Object obj) {
754 if (this == obj) {
755 return true;
756 }
757 if (!(obj instanceof BridingTableValue)) {
758 return false;
759 }
760 final BridingTableValue other = (BridingTableValue) obj;
761 return Objects.equals(this.popVlan, other.popVlan) &&
762 Objects.equals(this.portNumber, other.portNumber);
763 }
764
765 @Override
766 public int hashCode() {
767 return Objects.hash(popVlan, portNumber);
768 }
769 }
770
771 class RoutingTableKey {
772 DeviceId deviceId;
773 IpPrefix ipPrefix;
774
775 RoutingTableKey(DeviceId deviceId, IpPrefix ipPrefix) {
776 this.deviceId = deviceId;
777 this.ipPrefix = ipPrefix;
778 }
779
780 @Override
781 public boolean equals(final Object obj) {
782 if (this == obj) {
783 return true;
784 }
785 if (!(obj instanceof RoutingTableKey)) {
786 return false;
787 }
788 final RoutingTableKey other = (RoutingTableKey) obj;
789 return Objects.equals(this.deviceId, other.deviceId) &&
790 Objects.equals(this.ipPrefix, other.ipPrefix);
791 }
792
793 @Override
794 public int hashCode() {
795 return Objects.hash(deviceId, ipPrefix);
796 }
797 }
798
799 class RoutingTableValue {
800 PortNumber portNumber;
801 MacAddress macAddress;
802 VlanId vlanId;
803
804 RoutingTableValue(PortNumber portNumber, MacAddress macAddress, VlanId vlanId) {
805 this.portNumber = portNumber;
806 this.macAddress = macAddress;
807 this.vlanId = vlanId;
808 }
809
810 @Override
811 public boolean equals(final Object obj) {
812 if (this == obj) {
813 return true;
814 }
815 if (!(obj instanceof RoutingTableValue)) {
816 return false;
817 }
818 final RoutingTableValue other = (RoutingTableValue) obj;
819 return Objects.equals(this.portNumber, other.portNumber) &&
820 Objects.equals(this.macAddress, other.macAddress) &&
821 Objects.equals(this.vlanId, other.vlanId);
822 }
823
824 @Override
825 public int hashCode() {
826 return Objects.hash(portNumber, macAddress, vlanId);
827 }
828 }
829
Ray Milkeyfacf2862017-08-03 11:58:29 -0700830}