Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 1 | /* |
Brian O'Connor | 5ab426f | 2016-04-09 01:19:45 -0700 | [diff] [blame] | 2 | * Copyright 2016-present Open Networking Laboratory |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 3 | * |
| 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 | package org.onosproject.vpls; |
| 17 | |
Ray Milkey | 6e968eb | 2016-06-29 09:37:27 -0700 | [diff] [blame] | 18 | import java.util.Collections; |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 19 | import java.util.HashMap; |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 20 | import java.util.HashSet; |
Ray Milkey | 6e968eb | 2016-06-29 09:37:27 -0700 | [diff] [blame] | 21 | import java.util.List; |
Luca Prete | c21c6e6 | 2016-09-22 14:52:21 -0700 | [diff] [blame] | 22 | import java.util.Map; |
Ray Milkey | 6e968eb | 2016-06-29 09:37:27 -0700 | [diff] [blame] | 23 | import java.util.Set; |
| 24 | import java.util.concurrent.atomic.AtomicLong; |
| 25 | import java.util.stream.Collectors; |
| 26 | |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 27 | import com.google.common.collect.ImmutableList; |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 28 | import com.google.common.collect.Sets; |
| 29 | import com.google.common.collect.ImmutableSet; |
| 30 | import com.google.common.collect.SetMultimap; |
| 31 | import com.google.common.collect.HashMultimap; |
Luca Prete | c21c6e6 | 2016-09-22 14:52:21 -0700 | [diff] [blame] | 32 | import com.google.common.collect.Maps; |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 33 | import com.google.common.collect.Lists; |
| 34 | import com.google.common.collect.ImmutableSetMultimap; |
Ray Milkey | 6e968eb | 2016-06-29 09:37:27 -0700 | [diff] [blame] | 35 | import org.junit.After; |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 36 | import org.junit.Before; |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 37 | import org.junit.Test; |
| 38 | import org.onlab.packet.Ip4Address; |
| 39 | import org.onlab.packet.MacAddress; |
| 40 | import org.onlab.packet.VlanId; |
| 41 | import org.onosproject.TestApplicationId; |
| 42 | import org.onosproject.app.ApplicationService; |
| 43 | import org.onosproject.core.ApplicationId; |
| 44 | import org.onosproject.core.CoreService; |
| 45 | import org.onosproject.core.IdGenerator; |
| 46 | import org.onosproject.incubator.net.intf.Interface; |
Luca Prete | a885482 | 2016-04-26 16:30:55 -0700 | [diff] [blame] | 47 | import org.onosproject.incubator.net.intf.InterfaceListener; |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 48 | import org.onosproject.incubator.net.intf.InterfaceService; |
| 49 | import org.onosproject.net.ConnectPoint; |
| 50 | import org.onosproject.net.DefaultHost; |
| 51 | import org.onosproject.net.DeviceId; |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 52 | import org.onosproject.net.EncapsulationType; |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 53 | import org.onosproject.net.Host; |
| 54 | import org.onosproject.net.HostId; |
| 55 | import org.onosproject.net.HostLocation; |
| 56 | import org.onosproject.net.PortNumber; |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 57 | import org.onosproject.net.FilteredConnectPoint; |
| 58 | import org.onosproject.net.config.NetworkConfigService; |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 59 | import org.onosproject.net.flow.DefaultTrafficSelector; |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 60 | import org.onosproject.net.flow.TrafficSelector; |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 61 | import org.onosproject.net.flow.criteria.Criterion; |
| 62 | import org.onosproject.net.flow.criteria.VlanIdCriterion; |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 63 | import org.onosproject.net.host.HostEvent; |
| 64 | import org.onosproject.net.host.HostListener; |
| 65 | import org.onosproject.net.host.HostService; |
| 66 | import org.onosproject.net.host.HostServiceAdapter; |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 67 | import org.onosproject.net.intent.ConnectivityIntent; |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 68 | import org.onosproject.net.intent.Intent; |
| 69 | import org.onosproject.net.intent.IntentService; |
| 70 | import org.onosproject.net.intent.IntentServiceAdapter; |
| 71 | import org.onosproject.net.intent.IntentUtils; |
| 72 | import org.onosproject.net.intent.Key; |
| 73 | import org.onosproject.net.intent.MultiPointToSinglePointIntent; |
| 74 | import org.onosproject.net.intent.SinglePointToMultiPointIntent; |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 75 | import org.onosproject.net.intent.constraint.EncapsulationConstraint; |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 76 | import org.onosproject.net.provider.ProviderId; |
| 77 | import org.onosproject.routing.IntentSynchronizationAdminService; |
| 78 | import org.onosproject.routing.IntentSynchronizationService; |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 79 | import org.onosproject.vpls.config.VplsConfigurationService; |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 80 | |
| 81 | import static java.lang.String.format; |
Ray Milkey | 6e968eb | 2016-06-29 09:37:27 -0700 | [diff] [blame] | 82 | import static org.easymock.EasyMock.anyObject; |
| 83 | import static org.easymock.EasyMock.createMock; |
| 84 | import static org.easymock.EasyMock.expect; |
Luca Prete | a885482 | 2016-04-26 16:30:55 -0700 | [diff] [blame] | 85 | import static org.easymock.EasyMock.expectLastCall; |
Ray Milkey | 6e968eb | 2016-06-29 09:37:27 -0700 | [diff] [blame] | 86 | import static org.easymock.EasyMock.replay; |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 87 | import static org.junit.Assert.assertEquals; |
| 88 | import static org.junit.Assert.assertTrue; |
| 89 | |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 90 | import static org.onosproject.net.EncapsulationType.*; |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 91 | import static org.onosproject.vpls.IntentInstaller.PREFIX_BROADCAST; |
| 92 | import static org.onosproject.vpls.IntentInstaller.PREFIX_UNICAST; |
| 93 | |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 94 | /** |
| 95 | * Tests for the {@link Vpls} class. |
| 96 | */ |
| 97 | public class VplsTest { |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 98 | private static final String APP_NAME = "org.onosproject.vpls"; |
| 99 | private static final ApplicationId APPID = TestApplicationId.create(APP_NAME); |
| 100 | private static final String DASH = "-"; |
| 101 | private static final int PRIORITY_OFFSET = 1000; |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 102 | private static final String VPLS1 = "vpls1"; |
| 103 | private static final String VPLS2 = "vpls2"; |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 104 | |
| 105 | private static final PortNumber P1 = PortNumber.portNumber(1); |
| 106 | |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 107 | private static final DeviceId DID1 = getDeviceId(1); |
| 108 | private static final DeviceId DID2 = getDeviceId(2); |
| 109 | private static final DeviceId DID3 = getDeviceId(3); |
| 110 | private static final DeviceId DID4 = getDeviceId(4); |
| 111 | private static final DeviceId DID5 = getDeviceId(5); |
| 112 | private static final DeviceId DID6 = getDeviceId(6); |
| 113 | |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 114 | private static final ConnectPoint CP1 = new ConnectPoint(DID1, P1); |
| 115 | private static final ConnectPoint CP2 = new ConnectPoint(DID2, P1); |
| 116 | private static final ConnectPoint CP3 = new ConnectPoint(DID3, P1); |
| 117 | private static final ConnectPoint CP4 = new ConnectPoint(DID4, P1); |
| 118 | private static final ConnectPoint CP5 = new ConnectPoint(DID5, P1); |
| 119 | private static final ConnectPoint CP6 = new ConnectPoint(DID6, P1); |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 120 | |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 121 | private static final VlanId VLAN100 = VlanId.vlanId((short) 100); |
| 122 | private static final VlanId VLAN200 = VlanId.vlanId((short) 200); |
| 123 | private static final VlanId VLAN300 = VlanId.vlanId((short) 300); |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 124 | |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 125 | private static final MacAddress MAC1 = |
| 126 | MacAddress.valueOf("00:00:00:00:00:01"); |
| 127 | private static final MacAddress MAC2 = |
| 128 | MacAddress.valueOf("00:00:00:00:00:02"); |
| 129 | private static final MacAddress MAC3 = |
| 130 | MacAddress.valueOf("00:00:00:00:00:03"); |
| 131 | private static final MacAddress MAC4 = |
| 132 | MacAddress.valueOf("00:00:00:00:00:04"); |
| 133 | private static final MacAddress MAC5 = |
| 134 | MacAddress.valueOf("00:00:00:00:00:05"); |
| 135 | private static final MacAddress MAC6 = |
| 136 | MacAddress.valueOf("00:00:00:00:00:06"); |
| 137 | private static final MacAddress MAC7 = |
| 138 | MacAddress.valueOf("00:00:00:00:00:07"); |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 139 | |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 140 | private static final Ip4Address IP1 = Ip4Address.valueOf("192.168.1.1"); |
| 141 | private static final Ip4Address IP2 = Ip4Address.valueOf("192.168.1.2"); |
| 142 | |
| 143 | private static final HostId HID1 = HostId.hostId(MAC1, VLAN100); |
| 144 | private static final HostId HID2 = HostId.hostId(MAC2, VLAN100); |
| 145 | private static final HostId HID3 = HostId.hostId(MAC3, VLAN200); |
| 146 | private static final HostId HID4 = HostId.hostId(MAC4, VLAN200); |
| 147 | private static final HostId HID5 = HostId.hostId(MAC5, VLAN300); |
| 148 | private static final HostId HID6 = HostId.hostId(MAC6, VLAN300); |
| 149 | private static final HostId HID7 = HostId.hostId(MAC7, VLAN300); |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 150 | |
| 151 | private static final ProviderId PID = new ProviderId("of", "foo"); |
| 152 | |
Ray Milkey | 6e968eb | 2016-06-29 09:37:27 -0700 | [diff] [blame] | 153 | private static IdGenerator idGenerator; |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 154 | |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 155 | private static final Interface V100H1 = |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 156 | new Interface("v100h1", CP1, null, null, VLAN100); |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 157 | private static final Interface V100H2 = |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 158 | new Interface("v100h2", CP2, null, null, VLAN100); |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 159 | private static final Interface V200H1 = |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 160 | new Interface("v200h1", CP3, null, null, VLAN200); |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 161 | private static final Interface V200H2 = |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 162 | new Interface("v200h2", CP4, null, null, VLAN200); |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 163 | private static final Interface V300H1 = |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 164 | new Interface("v300h1", CP5, null, null, VLAN300); |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 165 | private static final Interface V300H2 = |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 166 | new Interface("v300h2", CP6, null, null, VLAN300); |
| 167 | |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 168 | private static final Host V100HOST1 = |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 169 | new DefaultHost(PID, HID1, MAC1, VLAN100, |
| 170 | getLocation(1), Collections.singleton(IP1)); |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 171 | private static final Host V100HOST2 = |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 172 | new DefaultHost(PID, HID2, MAC2, VLAN100, |
| 173 | getLocation(2), Sets.newHashSet()); |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 174 | private static final Host V200HOST1 = |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 175 | new DefaultHost(PID, HID3, MAC3, VLAN200, |
| 176 | getLocation(3), Collections.singleton(IP2)); |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 177 | private static final Host V200HOST2 = |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 178 | new DefaultHost(PID, HID4, MAC4, VLAN200, |
| 179 | getLocation(4), Sets.newHashSet()); |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 180 | private static final Host V300HOST1 = |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 181 | new DefaultHost(PID, HID5, MAC5, VLAN300, |
| 182 | getLocation(5), Sets.newHashSet()); |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 183 | private static final Host V300HOST2 = |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 184 | new DefaultHost(PID, HID6, MAC6, VLAN300, |
| 185 | getLocation(6), Sets.newHashSet()); |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 186 | private static final Host V300HOST3 = |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 187 | new DefaultHost(PID, HID7, MAC7, VLAN300, |
| 188 | getLocation(7), Sets.newHashSet()); |
| 189 | |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 190 | private static final Set<Interface> AVALIABLE_INTERFACES = |
| 191 | ImmutableSet.of(V100H1, V100H2, V200H1, V200H2, V300H1, V300H2); |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 192 | |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 193 | private static final Set<Host> AVALIABLE_HOSTS = |
| 194 | ImmutableSet.of(V100HOST1, V100HOST2, V200HOST1, |
| 195 | V200HOST2, V300HOST1, V300HOST2, V300HOST3); |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 196 | |
| 197 | private ApplicationService applicationService; |
| 198 | private CoreService coreService; |
| 199 | private HostListener hostListener; |
| 200 | private NetworkConfigService configService; |
| 201 | private Set<Host> hostsAvailable; |
| 202 | private HostService hostService; |
| 203 | private IntentService intentService; |
| 204 | private InterfaceService interfaceService; |
| 205 | private VplsConfigurationService vplsConfigService; |
| 206 | private Vpls vpls; |
| 207 | |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 208 | @Before |
| 209 | public void setUp() throws Exception { |
Ray Milkey | 6e968eb | 2016-06-29 09:37:27 -0700 | [diff] [blame] | 210 | idGenerator = new TestIdGenerator(); |
| 211 | Intent.bindIdGenerator(idGenerator); |
| 212 | |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 213 | applicationService = createMock(ApplicationService.class); |
| 214 | |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 215 | configService = createMock(NetworkConfigService.class); |
| 216 | |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 217 | coreService = createMock(CoreService.class); |
| 218 | expect(coreService.registerApplication(APP_NAME)) |
| 219 | .andReturn(APPID); |
| 220 | replay(coreService); |
| 221 | |
| 222 | hostsAvailable = Sets.newHashSet(); |
| 223 | hostService = new TestHostService(hostsAvailable); |
| 224 | |
| 225 | intentService = new TestIntentService(); |
| 226 | |
| 227 | TestIntentSynchronizer intentSynchronizer = |
| 228 | new TestIntentSynchronizer(intentService); |
| 229 | |
| 230 | interfaceService = createMock(InterfaceService.class); |
Luca Prete | a885482 | 2016-04-26 16:30:55 -0700 | [diff] [blame] | 231 | interfaceService.addListener(anyObject(InterfaceListener.class)); |
| 232 | expectLastCall().anyTimes(); |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 233 | addIfaceConfig(); |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 234 | |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 235 | SetMultimap<String, Interface> interfacesByVpls = |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 236 | HashMultimap.create(); |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 237 | interfacesByVpls.put(VPLS1, V100H1); |
| 238 | interfacesByVpls.put(VPLS1, V200H1); |
| 239 | interfacesByVpls.put(VPLS1, V300H1); |
| 240 | interfacesByVpls.put(VPLS2, V100H2); |
| 241 | interfacesByVpls.put(VPLS2, V200H2); |
| 242 | interfacesByVpls.put(VPLS2, V300H2); |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 243 | |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 244 | Map<String, EncapsulationType> encapByVpls = new HashMap<>(); |
| 245 | encapByVpls.put(VPLS1, VLAN); |
| 246 | encapByVpls.put(VPLS2, NONE); |
| 247 | |
| 248 | vplsConfigService = new TestVplsConfigService(interfacesByVpls, encapByVpls); |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 249 | |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 250 | vpls = new Vpls(); |
| 251 | vpls.applicationService = applicationService; |
| 252 | vpls.coreService = coreService; |
| 253 | vpls.hostService = hostService; |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 254 | vpls.vplsConfigService = vplsConfigService; |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 255 | vpls.intentService = intentService; |
| 256 | vpls.interfaceService = interfaceService; |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 257 | vpls.configService = configService; |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 258 | vpls.intentSynchronizer = intentSynchronizer; |
Yi Tseng | 28767f0 | 2016-09-13 04:27:20 -0700 | [diff] [blame] | 259 | |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 260 | } |
| 261 | |
Ray Milkey | 6e968eb | 2016-06-29 09:37:27 -0700 | [diff] [blame] | 262 | @After |
| 263 | public void tearDown() { |
| 264 | Intent.unbindIdGenerator(idGenerator); |
| 265 | } |
| 266 | |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 267 | /** |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 268 | * Creates the interface configuration. On devices 1 and 2 is configured |
| 269 | * an interface on port 1 with vlan 100. On devices 3 and 4 is configured |
| 270 | * an interface on port 1 with vlan 200. On device 5 and 6 is configured |
| 271 | * an interface on port 1 with vlan 300. |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 272 | */ |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 273 | private void addIfaceConfig() { |
| 274 | Set<Interface> interfaces = ImmutableSet.copyOf(AVALIABLE_INTERFACES); |
| 275 | Set<Interface> vlanOneSet = ImmutableSet.of(V100H1, V100H2); |
| 276 | Set<Interface> vlanTwoSet = ImmutableSet.of(V200H1, V200H2); |
| 277 | Set<Interface> vlanThreeSet = ImmutableSet.of(V300H1, V300H2); |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 278 | |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 279 | AVALIABLE_INTERFACES.forEach(intf -> { |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 280 | expect(interfaceService.getInterfacesByPort(intf.connectPoint())) |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 281 | .andReturn(Sets.newHashSet(intf)).anyTimes(); |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 282 | }); |
| 283 | expect(interfaceService.getInterfacesByVlan(VLAN100)) |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 284 | .andReturn(vlanOneSet).anyTimes(); |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 285 | expect(interfaceService.getInterfacesByVlan(VLAN200)) |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 286 | .andReturn(vlanTwoSet).anyTimes(); |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 287 | expect(interfaceService.getInterfacesByVlan(VLAN300)) |
| 288 | .andReturn(vlanThreeSet).anyTimes(); |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 289 | expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes(); |
| 290 | |
| 291 | replay(interfaceService); |
| 292 | } |
| 293 | |
| 294 | /** |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 295 | * Six ports are configured with VLANs but no hosts are registered by the |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 296 | * HostService. The first three ports have an interface configured on VPLS 1, |
| 297 | * the other three on VPLS 2. The number of intents expected is six: three for |
| 298 | * VPLS 1, three for VPLS 2. Six MP2SP intents. Checks if the number of intents |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 299 | * submitted to the intent framework is equal to the number of intents |
| 300 | * expected and if all intents are equivalent. |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 301 | */ |
| 302 | @Test |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 303 | public void activateNoHosts() { |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 304 | vpls.activate(); |
| 305 | |
Yi Tseng | 28767f0 | 2016-09-13 04:27:20 -0700 | [diff] [blame] | 306 | List<Intent> expectedIntents = Lists.newArrayList(); |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 307 | Set<FilteredConnectPoint> fcPoints; |
| 308 | |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 309 | fcPoints = buildFCPoints(ImmutableSet.of(V100H1, V200H1, V300H1)); |
| 310 | expectedIntents.addAll(generateVplsBrc(fcPoints, VPLS1, VLAN)); |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 311 | |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 312 | fcPoints = buildFCPoints(ImmutableSet.of(V100H2, V200H2, V300H2)); |
| 313 | expectedIntents.addAll(generateVplsBrc(fcPoints, VPLS2, NONE)); |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 314 | |
| 315 | checkIntents(expectedIntents); |
| 316 | } |
| 317 | |
| 318 | /** |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 319 | * Six ports are configured with VLANs and six hosts are registered by the |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 320 | * HostService. The first three ports have an interface configured on VPLS 1, |
| 321 | * the other three on VPLS 2. The number of intents expected is twelve: six |
| 322 | * for VLAN 1, six for VPLS 2. six sp2mp intents, six mp2sp intents. For VPLS 1 |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 323 | * IPs are added to demonstrate this doesn't influence the number of intents |
| 324 | * created. Checks if the number of intents submitted to the intent |
| 325 | * framework is equal to the number of intents expected and if all intents |
| 326 | * are equivalent. |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 327 | */ |
| 328 | @Test |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 329 | public void sixInterfacesConfiguredHostsPresent() { |
| 330 | hostsAvailable.addAll(AVALIABLE_HOSTS); |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 331 | |
| 332 | vpls.activate(); |
| 333 | |
Yi Tseng | 28767f0 | 2016-09-13 04:27:20 -0700 | [diff] [blame] | 334 | List<Intent> expectedIntents = Lists.newArrayList(); |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 335 | Set<FilteredConnectPoint> fcPoints; |
| 336 | Set<Host> hosts; |
| 337 | |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 338 | fcPoints = buildFCPoints(ImmutableSet.of(V100H1, V200H1, V300H1)); |
| 339 | hosts = ImmutableSet.of(V100HOST1, V200HOST1, V300HOST1); |
| 340 | expectedIntents.addAll(generateVplsBrc(fcPoints, VPLS1, VLAN)); |
| 341 | expectedIntents.addAll(generateVplsUni(fcPoints, hosts, VPLS1, VLAN)); |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 342 | |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 343 | fcPoints = buildFCPoints(ImmutableSet.of(V100H2, V200H2, V300H2)); |
| 344 | hosts = ImmutableSet.of(V100HOST2, V200HOST2, V300HOST2); |
| 345 | expectedIntents.addAll(generateVplsBrc(fcPoints, VPLS2, NONE)); |
| 346 | expectedIntents.addAll(generateVplsUni(fcPoints, hosts, VPLS2, NONE)); |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 347 | |
| 348 | checkIntents(expectedIntents); |
| 349 | } |
| 350 | |
| 351 | /** |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 352 | * Six ports are configured with VLANs and initially no hosts are registered |
| 353 | * by the HostService. The first three ports have an interface configured on |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 354 | * VPLS 1, the other three have an interface configured on VPLS 2. When the |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 355 | * module starts up, three hosts attached to device one, two and three - |
| 356 | * port 1, are registered by the HostService and events are sent to the |
| 357 | * application. sp2mp intents are created for all interfaces configured and |
| 358 | * mp2sp intents are created only for the hosts attached. |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 359 | * The number of intents expected is nine: six for VPLS 1, three for VPLS 2. |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 360 | * Six sp2mp intents, three mp2sp intents. IPs are added on the first two |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 361 | * hosts only to demonstrate this doesn't influence the number of intents |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 362 | * created. |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 363 | * An additional host is added on device seven - port 1, to demonstrate that |
| 364 | * the application does not generate intents, even if the interface uses the |
| 365 | * same VLAN Id of the other interfaces configured for the specifc VPLS. |
| 366 | * Checks if the number of intents submitted to the intent framework is equal |
| 367 | * to the number of intents expected and if all intents are equivalent. |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 368 | */ |
| 369 | @Test |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 370 | public void sixInterfacesThreeHostEventsSameVpls() { |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 371 | vpls.activate(); |
| 372 | |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 373 | List<Intent> expectedIntents = Lists.newArrayList(); |
| 374 | Set<FilteredConnectPoint> fcPoints; |
| 375 | Set<Host> hosts; |
| 376 | |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 377 | hostsAvailable.addAll(Sets.newHashSet(V100HOST1, V200HOST1, V300HOST1, V300HOST3)); |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 378 | |
| 379 | hostsAvailable.forEach(host -> |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 380 | hostListener.event(new HostEvent(HostEvent.Type.HOST_ADDED, host))); |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 381 | |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 382 | fcPoints = buildFCPoints(ImmutableSet.of(V100H1, V200H1, V300H1)); |
| 383 | hosts = ImmutableSet.of(V100HOST1, V200HOST1, V300HOST1); |
| 384 | expectedIntents.addAll(generateVplsBrc(fcPoints, VPLS1, VLAN)); |
| 385 | expectedIntents.addAll(generateVplsUni(fcPoints, hosts, VPLS1, VLAN)); |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 386 | |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 387 | fcPoints = buildFCPoints(ImmutableSet.of(V100H2, V200H2, V300H2)); |
| 388 | expectedIntents.addAll(generateVplsBrc(fcPoints, VPLS2, NONE)); |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 389 | |
| 390 | checkIntents(expectedIntents); |
| 391 | } |
| 392 | |
| 393 | /** |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 394 | * Generates a list of the expected sp2mp intents for a VPLS. |
| 395 | * |
| 396 | * @param fcPoints the filtered connect point |
| 397 | * @param name the name of the VPLS |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 398 | * @param encap the encapsulation type |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 399 | * @return the list of expected sp2mp intents for the given VPLS |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 400 | */ |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 401 | private List<SinglePointToMultiPointIntent> |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 402 | generateVplsBrc(Set<FilteredConnectPoint> fcPoints, String name, EncapsulationType encap) { |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 403 | List<SinglePointToMultiPointIntent> intents = Lists.newArrayList(); |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 404 | |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 405 | fcPoints.forEach(point -> { |
| 406 | Set<FilteredConnectPoint> otherPoints = |
| 407 | fcPoints.stream() |
| 408 | .filter(fcp -> !fcp.equals(point)) |
| 409 | .collect(Collectors.toSet()); |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 410 | |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 411 | Key brckey = buildKey(PREFIX_BROADCAST, |
| 412 | point.connectPoint(), name, MacAddress.BROADCAST); |
| 413 | |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 414 | intents.add(buildBrcIntent(brckey, point, otherPoints, encap)); |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 415 | }); |
| 416 | |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 417 | return intents; |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 418 | } |
| 419 | |
| 420 | /** |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 421 | * Generates a list of expected mp2sp intents for a given VPLS. |
| 422 | * |
| 423 | * @param fcPoints the filtered connect point |
| 424 | * @param hosts the hosts |
| 425 | * @param name the name of the VPLS |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 426 | * @param encap the encapsulation type |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 427 | * @return the list of expected mp2sp intents for the given VPLS |
| 428 | */ |
| 429 | private List<MultiPointToSinglePointIntent> |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 430 | generateVplsUni(Set<FilteredConnectPoint> fcPoints, Set<Host> hosts, |
| 431 | String name, EncapsulationType encap) { |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 432 | List<MultiPointToSinglePointIntent> intents = Lists.newArrayList(); |
| 433 | |
| 434 | hosts.forEach(host -> { |
| 435 | FilteredConnectPoint hostPoint = getHostPoint(host, fcPoints); |
| 436 | |
| 437 | Set<FilteredConnectPoint> otherPoints = |
| 438 | fcPoints.stream() |
| 439 | .filter(fcp -> !fcp.equals(hostPoint)) |
| 440 | .collect(Collectors.toSet()); |
| 441 | |
| 442 | Key uniKey = buildKey(PREFIX_UNICAST, |
| 443 | host.location(), name, host.mac()); |
| 444 | |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 445 | intents.add(buildUniIntent(uniKey, otherPoints, hostPoint, host, encap)); |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 446 | }); |
| 447 | |
| 448 | return intents; |
| 449 | } |
| 450 | |
| 451 | /** |
| 452 | * Checks if the number of intents submitted to the intent framework is equal |
| 453 | * to the number of intents expected and if all intents are equivalent. |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 454 | * |
| 455 | * @param intents the list of intents expected |
| 456 | */ |
| 457 | private void checkIntents(List<Intent> intents) { |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 458 | assertEquals("The number of intents submitted differs from the number" + |
| 459 | "of intents expected", |
| 460 | intents.size(), intentService.getIntentCount()); |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 461 | |
| 462 | for (Intent intentOne : intents) { |
| 463 | boolean found = false; |
| 464 | for (Intent intentTwo : intentService.getIntents()) { |
| 465 | if (intentOne.key().equals(intentTwo.key())) { |
| 466 | found = true; |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 467 | assertTrue(format("The intent submitted is different from" + |
| 468 | "the intent expected", |
| 469 | intentOne, intentTwo), |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 470 | IntentUtils.intentsAreEqual(intentOne, intentTwo)); |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 471 | break; |
| 472 | } |
| 473 | } |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 474 | assertTrue("The intent submitted is not equal to any of the expected" + |
| 475 | "intents", found); |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 476 | } |
| 477 | } |
| 478 | |
| 479 | /** |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 480 | * Builds a broadcast intent. |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 481 | * |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 482 | * @param key the key to identify the intent |
| 483 | * @param src the ingress connect point |
| 484 | * @param dsts the egress connect points |
| 485 | * @return the generated single-point to multi-point intent |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 486 | */ |
| 487 | private SinglePointToMultiPointIntent buildBrcIntent(Key key, |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 488 | FilteredConnectPoint src, |
| 489 | Set<FilteredConnectPoint> dsts, |
| 490 | EncapsulationType encap) { |
| 491 | SinglePointToMultiPointIntent.Builder intentBuilder; |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 492 | |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 493 | TrafficSelector selector = DefaultTrafficSelector.builder() |
| 494 | .matchEthDst(MacAddress.BROADCAST) |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 495 | .build(); |
| 496 | |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 497 | intentBuilder = SinglePointToMultiPointIntent.builder() |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 498 | .appId(APPID) |
| 499 | .key(key) |
| 500 | .selector(selector) |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 501 | .filteredIngressPoint(src) |
| 502 | .filteredEgressPoints(dsts) |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 503 | .priority(PRIORITY_OFFSET); |
| 504 | |
| 505 | encap(intentBuilder, encap); |
| 506 | |
| 507 | return intentBuilder.build(); |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 508 | } |
| 509 | |
| 510 | /** |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 511 | * Builds a unicast intent. |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 512 | * |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 513 | * @param key the key to identify the intent |
| 514 | * @param srcs the ingress connect points |
| 515 | * @param dst the egress connect point |
| 516 | * @param host the destination Host |
| 517 | * @return the generated multi-point to single-point intent |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 518 | */ |
| 519 | private MultiPointToSinglePointIntent buildUniIntent(Key key, |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 520 | Set<FilteredConnectPoint> srcs, |
| 521 | FilteredConnectPoint dst, |
| 522 | Host host, |
| 523 | EncapsulationType encap) { |
| 524 | MultiPointToSinglePointIntent.Builder intentBuilder; |
| 525 | |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 526 | TrafficSelector selector = DefaultTrafficSelector.builder() |
| 527 | .matchEthDst(host.mac()) |
| 528 | .build(); |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 529 | |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 530 | intentBuilder = MultiPointToSinglePointIntent.builder() |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 531 | .appId(APPID) |
| 532 | .key(key) |
| 533 | .selector(selector) |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 534 | .filteredIngressPoints(srcs) |
| 535 | .filteredEgressPoint(dst) |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 536 | .priority(PRIORITY_OFFSET); |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 537 | |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 538 | encap(intentBuilder, encap); |
| 539 | |
| 540 | return intentBuilder.build(); |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 541 | } |
| 542 | |
| 543 | /** |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 544 | * Returns the filtered connect point associated to a given host. |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 545 | * |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 546 | * @param host the target host |
| 547 | * @param fcps the filtered connected points |
| 548 | * @return the filtered connect point associated to the given host; null |
| 549 | * otherwise |
| 550 | */ |
| 551 | private FilteredConnectPoint getHostPoint(Host host, |
| 552 | Set<FilteredConnectPoint> fcps) { |
| 553 | return fcps.stream() |
| 554 | .filter(fcp -> fcp.connectPoint().equals(host.location())) |
| 555 | .filter(fcp -> { |
| 556 | VlanIdCriterion vlanCriterion = |
| 557 | (VlanIdCriterion) fcp.trafficSelector(). |
| 558 | getCriterion(Criterion.Type.VLAN_VID); |
| 559 | |
| 560 | return vlanCriterion != null && |
| 561 | vlanCriterion.vlanId().equals(host.vlan()); |
| 562 | }) |
| 563 | .findFirst() |
| 564 | .orElse(null); |
| 565 | } |
| 566 | |
| 567 | /** |
| 568 | * Computes a set of filtered connect points from given interfaces. |
| 569 | * |
| 570 | * @param interfaces the interfaces belonging to the VPLS |
| 571 | * @return the set of filtered connect points |
| 572 | */ |
| 573 | private Set<FilteredConnectPoint> buildFCPoints(Set<Interface> interfaces) { |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 574 | // Build all filtered connected point for the VPLS |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 575 | return interfaces |
| 576 | .stream() |
| 577 | .map(intf -> { |
| 578 | TrafficSelector.Builder selectorBuilder = |
| 579 | DefaultTrafficSelector.builder(); |
| 580 | |
| 581 | if (!intf.vlan().equals(VlanId.NONE)) { |
| 582 | selectorBuilder.matchVlanId(intf.vlan()); |
| 583 | } |
| 584 | |
| 585 | return new FilteredConnectPoint(intf.connectPoint(), |
| 586 | selectorBuilder.build()); |
| 587 | }) |
| 588 | .collect(Collectors.toSet()); |
| 589 | } |
| 590 | |
| 591 | /** |
| 592 | * Builds an intent Key either for a single-point to multi-point or |
| 593 | * multi-point to single-point intent, based on a prefix that defines |
| 594 | * the intent type, the connection point representing the source or the |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 595 | * destination and the VLAN Id representing the VPLS. |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 596 | * |
| 597 | * @param prefix the key prefix |
| 598 | * @param cPoint the ingress/egress connect point |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 599 | * @param vplsName the VPLS name |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 600 | * @param hostMac the ingress/egress MAC address |
| 601 | * @return the key to identify the intent |
| 602 | */ |
| 603 | private Key buildKey(String prefix, |
| 604 | ConnectPoint cPoint, |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 605 | String vplsName, |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 606 | MacAddress hostMac) { |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 607 | String keyString = vplsName + |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 608 | DASH + |
| 609 | prefix + |
| 610 | DASH + |
| 611 | cPoint.deviceId() + |
| 612 | DASH + |
| 613 | cPoint.port() + |
| 614 | DASH + |
| 615 | hostMac; |
| 616 | |
| 617 | return Key.of(keyString, APPID); |
| 618 | } |
| 619 | |
| 620 | /** |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 621 | * Adds an encapsulation constraint to the builder given, if encap is not |
| 622 | * equal to NONE. |
| 623 | * |
| 624 | * @param builder the intent builder |
| 625 | * @param encap the encapsulation type |
| 626 | */ |
| 627 | private static void encap(ConnectivityIntent.Builder builder, |
| 628 | EncapsulationType encap) { |
| 629 | if (!encap.equals(NONE)) { |
| 630 | builder.constraints(ImmutableList.of( |
| 631 | new EncapsulationConstraint(encap))); |
| 632 | } |
| 633 | } |
| 634 | |
| 635 | /** |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 636 | * Returns the device Id of the ith device. |
| 637 | * |
| 638 | * @param i the device to get the Id of |
| 639 | * @return the device Id |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 640 | */ |
| 641 | private static DeviceId getDeviceId(int i) { |
| 642 | return DeviceId.deviceId("" + i); |
| 643 | } |
| 644 | |
| 645 | private static HostLocation getLocation(int i) { |
| 646 | return new HostLocation(new ConnectPoint(getDeviceId(i), P1), 123L); |
| 647 | } |
| 648 | |
| 649 | /** |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 650 | * Represents a fake IntentService class that allows to store and retrieve |
| 651 | * intents without implementing the IntentService logic. |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 652 | */ |
| 653 | private class TestIntentService extends IntentServiceAdapter { |
| 654 | |
Luca Prete | c21c6e6 | 2016-09-22 14:52:21 -0700 | [diff] [blame] | 655 | private Map<Key, Intent> intents; |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 656 | |
| 657 | public TestIntentService() { |
Luca Prete | c21c6e6 | 2016-09-22 14:52:21 -0700 | [diff] [blame] | 658 | intents = Maps.newHashMap(); |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 659 | } |
| 660 | |
| 661 | @Override |
| 662 | public void submit(Intent intent) { |
Luca Prete | c21c6e6 | 2016-09-22 14:52:21 -0700 | [diff] [blame] | 663 | intents.put(intent.key(), intent); |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 664 | } |
| 665 | |
| 666 | @Override |
| 667 | public long getIntentCount() { |
| 668 | return intents.size(); |
| 669 | } |
| 670 | |
| 671 | @Override |
| 672 | public Iterable<Intent> getIntents() { |
Luca Prete | c21c6e6 | 2016-09-22 14:52:21 -0700 | [diff] [blame] | 673 | return intents.values(); |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 674 | } |
| 675 | |
| 676 | @Override |
| 677 | public Intent getIntent(Key intentKey) { |
Luca Prete | c21c6e6 | 2016-09-22 14:52:21 -0700 | [diff] [blame] | 678 | for (Intent intent : intents.values()) { |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 679 | if (intent.key().equals(intentKey)) { |
| 680 | return intent; |
| 681 | } |
| 682 | } |
| 683 | return null; |
| 684 | } |
| 685 | } |
| 686 | |
| 687 | /** |
| 688 | * Represents a fake HostService class which allows to add hosts manually |
| 689 | * in each test, when needed. |
| 690 | */ |
| 691 | private class TestHostService extends HostServiceAdapter { |
| 692 | |
| 693 | private Set<Host> hosts; |
| 694 | |
| 695 | public TestHostService(Set<Host> hosts) { |
| 696 | this.hosts = hosts; |
| 697 | } |
| 698 | |
| 699 | @Override |
| 700 | public void addListener(HostListener listener) { |
| 701 | VplsTest.this.hostListener = listener; |
| 702 | } |
| 703 | |
| 704 | @Override |
| 705 | public Set<Host> getConnectedHosts(ConnectPoint connectPoint) { |
| 706 | return hosts.stream() |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 707 | .filter(h -> h.location().equals(connectPoint)) |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 708 | .collect(Collectors.toSet()); |
| 709 | } |
| 710 | |
| 711 | } |
| 712 | |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 713 | /** |
| 714 | * Represents a fake IdGenerator class for intents. |
| 715 | */ |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 716 | private static class TestIdGenerator implements IdGenerator { |
| 717 | |
| 718 | private final AtomicLong id = new AtomicLong(0); |
| 719 | |
| 720 | @Override |
| 721 | public long getNewId() { |
| 722 | return id.getAndIncrement(); |
| 723 | } |
| 724 | |
| 725 | } |
| 726 | |
| 727 | /** |
| 728 | * Test IntentSynchronizer that passes all intents straight through to the |
| 729 | * intent service. |
| 730 | */ |
| 731 | private class TestIntentSynchronizer implements IntentSynchronizationService, |
| 732 | IntentSynchronizationAdminService { |
| 733 | |
| 734 | private final IntentService intentService; |
| 735 | |
| 736 | /** |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 737 | * Creates a new intent test synchronizer. |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 738 | * |
| 739 | * @param intentService intent service |
| 740 | */ |
| 741 | public TestIntentSynchronizer(IntentService intentService) { |
| 742 | this.intentService = intentService; |
| 743 | } |
| 744 | |
| 745 | @Override |
| 746 | public void submit(Intent intent) { |
| 747 | intentService.submit(intent); |
| 748 | } |
| 749 | |
| 750 | @Override |
| 751 | public void withdraw(Intent intent) { |
| 752 | intentService.withdraw(intent); |
| 753 | } |
| 754 | |
| 755 | @Override |
| 756 | public void modifyPrimary(boolean isPrimary) { |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 757 | } |
| 758 | |
| 759 | @Override |
| 760 | public void removeIntents() { |
Luca Prete | 2705d66 | 2016-04-29 15:30:23 -0700 | [diff] [blame] | 761 | } |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 762 | |
Luca Prete | 2705d66 | 2016-04-29 15:30:23 -0700 | [diff] [blame] | 763 | @Override |
| 764 | public void removeIntentsByAppId(ApplicationId applicationId) { |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 765 | } |
| 766 | } |
| 767 | |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 768 | /** |
| 769 | * Represents a fake VplsConfigService class which is needed for testing. |
| 770 | */ |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 771 | private class TestVplsConfigService extends VplsConfigurationServiceAdapter { |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 772 | |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 773 | private final SetMultimap<String, Interface> ifacesByVplsName; |
| 774 | private final Map<String, EncapsulationType> encapsByVplsName; |
| 775 | |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 776 | private Set<String> vplsAffectByApi = new HashSet<>(); |
| 777 | |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 778 | TestVplsConfigService(SetMultimap<String, Interface> ifacesByVplsName, |
| 779 | Map<String, EncapsulationType> encapsByVplsName) { |
| 780 | this.ifacesByVplsName = ifacesByVplsName; |
| 781 | this.encapsByVplsName = encapsByVplsName; |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 782 | } |
| 783 | |
| 784 | @Override |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 785 | public void addVpls(String vplsName, Set<String> ifaceNames, String encap) { |
| 786 | if (!ifacesByVplsName.containsKey(vplsName)) { |
| 787 | ifaceNames.forEach(ifaceName -> { |
| 788 | AVALIABLE_INTERFACES.forEach(iface -> { |
| 789 | if (iface.name().equals(ifaceName)) { |
| 790 | ifacesByVplsName.put(vplsName, iface); |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 791 | } |
| 792 | }); |
| 793 | }); |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 794 | encapsByVplsName.put(vplsName, valueOf(encap)); |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 795 | } |
| 796 | } |
| 797 | |
| 798 | @Override |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 799 | public void removeVpls(String vplsName) { |
| 800 | if (ifacesByVplsName.containsKey(vplsName)) { |
| 801 | ifacesByVplsName.removeAll(vplsName); |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 802 | } |
| 803 | } |
| 804 | |
| 805 | @Override |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 806 | public void addIface(String vplsName, String iface) { |
| 807 | if (!ifacesByVplsName.containsKey(vplsName)) { |
| 808 | AVALIABLE_INTERFACES.forEach(intf -> { |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 809 | if (intf.name().equals(iface)) { |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 810 | ifacesByVplsName.put(vplsName, intf); |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 811 | } |
| 812 | }); |
| 813 | } |
| 814 | } |
| 815 | |
| 816 | @Override |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 817 | public void setEncap(String vplsName, String encap) { |
| 818 | encapsByVplsName.put(vplsName, EncapsulationType.enumFromString(encap)); |
| 819 | } |
| 820 | |
| 821 | @Override |
| 822 | public void removeIface(String iface) { |
| 823 | SetMultimap<String, Interface> search = HashMultimap.create(ifacesByVplsName); |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 824 | search.entries().forEach(e -> { |
| 825 | if (e.getValue().name().equals(iface)) { |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 826 | ifacesByVplsName.remove(e.getKey(), iface); |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 827 | } |
| 828 | }); |
| 829 | } |
| 830 | |
| 831 | @Override |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 832 | public void cleanVplsConfig() { |
| 833 | ifacesByVplsName.clear(); |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 834 | } |
| 835 | |
| 836 | @Override |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 837 | public EncapsulationType encap(String vplsName) { |
| 838 | EncapsulationType encap = null; |
| 839 | if (encapsByVplsName.containsKey(vplsName)) { |
| 840 | encap = encapsByVplsName.get(vplsName); |
| 841 | } |
| 842 | return encap; |
| 843 | } |
| 844 | |
| 845 | @Override |
| 846 | public Set<String> vplsAffectedByApi() { |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 847 | Set<String> vplsNames = ImmutableSet.copyOf(vplsAffectByApi); |
| 848 | |
| 849 | vplsAffectByApi.clear(); |
| 850 | |
| 851 | return vplsNames; |
| 852 | } |
| 853 | |
| 854 | @Override |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 855 | public Set<Interface> allIfaces() { |
| 856 | return ifacesByVplsName.values() |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 857 | .stream() |
| 858 | .collect(Collectors.toSet()); |
| 859 | } |
| 860 | |
| 861 | @Override |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 862 | public Set<Interface> ifaces(String name) { |
| 863 | return ifacesByVplsName.get(name) |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 864 | .stream() |
| 865 | .collect(Collectors.toSet()); |
| 866 | } |
| 867 | |
| 868 | @Override |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 869 | public Set<String> vplsNames() { |
| 870 | return ifacesByVplsName.keySet(); |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 871 | } |
| 872 | |
| 873 | @Override |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 874 | public Set<String> vplsNamesOld() { |
| 875 | return ifacesByVplsName.keySet(); |
| 876 | } |
| 877 | |
| 878 | public SetMultimap<String, Interface> ifacesByVplsName() { |
| 879 | return ImmutableSetMultimap.copyOf(ifacesByVplsName); |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 880 | } |
| 881 | |
| 882 | @Override |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 883 | public SetMultimap<String, Interface> ifacesByVplsName(VlanId vlan, |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 884 | ConnectPoint connectPoint) { |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 885 | String vplsName = |
| 886 | ifacesByVplsName.entries().stream() |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 887 | .filter(e -> e.getValue().connectPoint().equals(connectPoint)) |
| 888 | .filter(e -> e.getValue().vlan().equals(vlan)) |
| 889 | .map(e -> e.getKey()) |
| 890 | .findFirst() |
| 891 | .orElse(null); |
| 892 | SetMultimap<String, Interface> result = HashMultimap.create(); |
Luca Prete | 092e895 | 2016-10-26 16:25:56 +0200 | [diff] [blame^] | 893 | if (vplsName != null && ifacesByVplsName.containsKey(vplsName)) { |
| 894 | ifacesByVplsName.get(vplsName) |
| 895 | .forEach(intf -> result.put(vplsName, intf)); |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 896 | return result; |
| 897 | } |
| 898 | return null; |
| 899 | } |
nosignal | 5fd282e | 2016-09-16 16:11:40 -0700 | [diff] [blame] | 900 | } |
Luca Prete | 9c2ee07 | 2016-02-16 11:00:44 -0800 | [diff] [blame] | 901 | } |