blob: 17f43fda13cdf84285110f4249c08fee75166aa8 [file] [log] [blame]
lishuai6c56f5e2015-11-17 16:38:19 +08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
lishuai6c56f5e2015-11-17 16:38:19 +08003 *
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 */
16package org.onosproject.vtn.manager.impl;
17
jiangruic69a7fd2015-11-19 15:40:01 +080018import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST;
lishuai6c56f5e2015-11-17 16:38:19 +080019import static org.slf4j.LoggerFactory.getLogger;
20
lishuai858efd32015-12-04 14:30:36 +080021import java.util.ArrayList;
lishuaib43dbf72016-01-06 11:11:35 +080022import java.util.Arrays;
lishuai6c56f5e2015-11-17 16:38:19 +080023import java.util.Collection;
24import java.util.HashMap;
25import java.util.HashSet;
26import java.util.Iterator;
jiangruic69a7fd2015-11-19 15:40:01 +080027import java.util.List;
lishuai6c56f5e2015-11-17 16:38:19 +080028import java.util.Map;
29import java.util.Set;
lishuai74f2d532015-12-10 17:03:34 +080030import java.util.concurrent.ConcurrentHashMap;
lishuai858efd32015-12-04 14:30:36 +080031import java.util.stream.Collectors;
lishuai6c56f5e2015-11-17 16:38:19 +080032
33import org.apache.felix.scr.annotations.Activate;
34import org.apache.felix.scr.annotations.Component;
35import org.apache.felix.scr.annotations.Deactivate;
36import org.apache.felix.scr.annotations.Reference;
37import org.apache.felix.scr.annotations.ReferenceCardinality;
38import org.apache.felix.scr.annotations.Service;
jiangruic69a7fd2015-11-19 15:40:01 +080039import org.onlab.packet.Ip4Address;
lishuai6c56f5e2015-11-17 16:38:19 +080040import org.onlab.packet.IpAddress;
41import org.onlab.packet.MacAddress;
42import org.onlab.util.KryoNamespace;
43import org.onosproject.core.ApplicationId;
44import org.onosproject.core.CoreService;
45import org.onosproject.mastership.MastershipService;
lishuai858efd32015-12-04 14:30:36 +080046import org.onosproject.net.AnnotationKeys;
lishuai6c56f5e2015-11-17 16:38:19 +080047import org.onosproject.net.Device;
48import org.onosproject.net.DeviceId;
49import org.onosproject.net.Host;
lishuai858efd32015-12-04 14:30:36 +080050import org.onosproject.net.HostId;
lishuai6c56f5e2015-11-17 16:38:19 +080051import org.onosproject.net.Port;
52import org.onosproject.net.PortNumber;
53import org.onosproject.net.behaviour.BridgeConfig;
54import org.onosproject.net.behaviour.BridgeDescription;
jiangruic69a7fd2015-11-19 15:40:01 +080055import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
lishuai6c56f5e2015-11-17 16:38:19 +080056import org.onosproject.net.config.NetworkConfigService;
57import org.onosproject.net.config.basics.BasicDeviceConfig;
58import org.onosproject.net.device.DeviceEvent;
59import org.onosproject.net.device.DeviceListener;
60import org.onosproject.net.device.DeviceService;
61import org.onosproject.net.driver.DriverHandler;
62import org.onosproject.net.driver.DriverService;
jiangruic69a7fd2015-11-19 15:40:01 +080063import org.onosproject.net.flow.DefaultTrafficTreatment;
64import org.onosproject.net.flow.TrafficTreatment.Builder;
65import org.onosproject.net.flow.instructions.ExtensionTreatment;
lishuai6c56f5e2015-11-17 16:38:19 +080066import org.onosproject.net.flowobjective.Objective;
jiangruic69a7fd2015-11-19 15:40:01 +080067import org.onosproject.net.group.DefaultGroupBucket;
68import org.onosproject.net.group.DefaultGroupDescription;
69import org.onosproject.net.group.DefaultGroupKey;
70import org.onosproject.net.group.GroupBucket;
71import org.onosproject.net.group.GroupBuckets;
72import org.onosproject.net.group.GroupDescription;
73import org.onosproject.net.group.GroupKey;
74import org.onosproject.net.group.GroupService;
lishuai6c56f5e2015-11-17 16:38:19 +080075import org.onosproject.net.host.HostEvent;
76import org.onosproject.net.host.HostListener;
77import org.onosproject.net.host.HostService;
78import org.onosproject.store.serializers.KryoNamespaces;
lishuaib43dbf72016-01-06 11:11:35 +080079import org.onosproject.store.service.ConsistentMap;
lishuai6c56f5e2015-11-17 16:38:19 +080080import org.onosproject.store.service.EventuallyConsistentMap;
81import org.onosproject.store.service.LogicalClockService;
lishuaib43dbf72016-01-06 11:11:35 +080082import org.onosproject.store.service.Serializer;
lishuai6c56f5e2015-11-17 16:38:19 +080083import org.onosproject.store.service.StorageService;
lishuaib43dbf72016-01-06 11:11:35 +080084import org.onosproject.store.service.Versioned;
Jonathan Hart51539b82015-10-29 09:53:04 -070085import org.onosproject.vtn.manager.VtnService;
lishuai858efd32015-12-04 14:30:36 +080086import org.onosproject.vtn.table.ArpService;
lishuai6c56f5e2015-11-17 16:38:19 +080087import org.onosproject.vtn.table.ClassifierService;
lishuai858efd32015-12-04 14:30:36 +080088import org.onosproject.vtn.table.DnatService;
lishuai6c56f5e2015-11-17 16:38:19 +080089import org.onosproject.vtn.table.L2ForwardService;
lishuai858efd32015-12-04 14:30:36 +080090import org.onosproject.vtn.table.L3ForwardService;
91import org.onosproject.vtn.table.SnatService;
lishuai74f2d532015-12-10 17:03:34 +080092import org.onosproject.vtn.table.impl.ArpServiceImpl;
lishuai6c56f5e2015-11-17 16:38:19 +080093import org.onosproject.vtn.table.impl.ClassifierServiceImpl;
lishuai74f2d532015-12-10 17:03:34 +080094import org.onosproject.vtn.table.impl.DnatServiceImpl;
lishuai6c56f5e2015-11-17 16:38:19 +080095import org.onosproject.vtn.table.impl.L2ForwardServiceImpl;
lishuai74f2d532015-12-10 17:03:34 +080096import org.onosproject.vtn.table.impl.L3ForwardServiceImpl;
97import org.onosproject.vtn.table.impl.SnatServiceImpl;
lishuai6c56f5e2015-11-17 16:38:19 +080098import org.onosproject.vtn.util.DataPathIdGenerator;
99import org.onosproject.vtn.util.VtnConfig;
100import org.onosproject.vtn.util.VtnData;
lishuai7dc63d92015-11-27 17:15:25 +0800101import org.onosproject.vtnrsc.AllowedAddressPair;
102import org.onosproject.vtnrsc.BindingHostId;
103import org.onosproject.vtnrsc.DefaultVirtualPort;
104import org.onosproject.vtnrsc.FixedIp;
lishuai858efd32015-12-04 14:30:36 +0800105import org.onosproject.vtnrsc.FloatingIp;
lishuai858efd32015-12-04 14:30:36 +0800106import org.onosproject.vtnrsc.RouterInterface;
lishuai7dc63d92015-11-27 17:15:25 +0800107import org.onosproject.vtnrsc.SecurityGroup;
lishuai6c56f5e2015-11-17 16:38:19 +0800108import org.onosproject.vtnrsc.SegmentationId;
109import org.onosproject.vtnrsc.SubnetId;
110import org.onosproject.vtnrsc.TenantId;
111import org.onosproject.vtnrsc.TenantNetwork;
112import org.onosproject.vtnrsc.TenantNetworkId;
lishuai8798bbe2016-05-05 16:02:03 +0800113import org.onosproject.vtnrsc.TenantRouter;
lishuai6c56f5e2015-11-17 16:38:19 +0800114import org.onosproject.vtnrsc.VirtualPort;
115import org.onosproject.vtnrsc.VirtualPortId;
lishuai858efd32015-12-04 14:30:36 +0800116import org.onosproject.vtnrsc.event.VtnRscEvent;
117import org.onosproject.vtnrsc.event.VtnRscEventFeedback;
118import org.onosproject.vtnrsc.event.VtnRscListener;
119import org.onosproject.vtnrsc.floatingip.FloatingIpService;
lishuai858efd32015-12-04 14:30:36 +0800120import org.onosproject.vtnrsc.routerinterface.RouterInterfaceService;
121import org.onosproject.vtnrsc.service.VtnRscService;
122import org.onosproject.vtnrsc.subnet.SubnetService;
lishuai6c56f5e2015-11-17 16:38:19 +0800123import org.onosproject.vtnrsc.tenantnetwork.TenantNetworkService;
124import org.onosproject.vtnrsc.virtualport.VirtualPortService;
125import org.slf4j.Logger;
126
jiangruic69a7fd2015-11-19 15:40:01 +0800127import com.google.common.collect.Lists;
lishuai6c56f5e2015-11-17 16:38:19 +0800128import com.google.common.collect.Sets;
129
130/**
131 * Provides implementation of VTNService.
132 */
133@Component(immediate = true)
134@Service
Jonathan Hart51539b82015-10-29 09:53:04 -0700135public class VtnManager implements VtnService {
lishuai6c56f5e2015-11-17 16:38:19 +0800136 private final Logger log = getLogger(getClass());
137 private static final String APP_ID = "org.onosproject.app.vtn";
138
139 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
140 protected NetworkConfigService configService;
141
142 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
143 protected DeviceService deviceService;
144
145 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
146 protected HostService hostService;
147
148 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
149 protected CoreService coreService;
150
151 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
152 protected StorageService storageService;
153
154 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
155 protected TenantNetworkService tenantNetworkService;
156
157 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
158 protected VirtualPortService virtualPortService;
159
160 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
161 protected DriverService driverService;
162
163 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
164 protected LogicalClockService clockService;
165
166 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
167 protected MastershipService mastershipService;
168
jiangruic69a7fd2015-11-19 15:40:01 +0800169 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
170 protected GroupService groupService;
171
lishuai858efd32015-12-04 14:30:36 +0800172 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
173 protected SubnetService subnetService;
174
175 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
176 protected VtnRscService vtnRscService;
177
178 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
179 protected FloatingIpService floatingIpService;
180
181 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
lishuai858efd32015-12-04 14:30:36 +0800182 protected RouterInterfaceService routerInterfaceService;
183
lishuai6c56f5e2015-11-17 16:38:19 +0800184 private ApplicationId appId;
185 private ClassifierService classifierService;
186 private L2ForwardService l2ForwardService;
lishuai858efd32015-12-04 14:30:36 +0800187 private ArpService arpService;
188 private L3ForwardService l3ForwardService;
189 private SnatService snatService;
190 private DnatService dnatService;
lishuai6c56f5e2015-11-17 16:38:19 +0800191
192 private final HostListener hostListener = new InnerHostListener();
193 private final DeviceListener deviceListener = new InnerDeviceListener();
lishuai858efd32015-12-04 14:30:36 +0800194 private final VtnRscListener l3EventListener = new VtnL3EventListener();
lishuai6c56f5e2015-11-17 16:38:19 +0800195
lishuaib43dbf72016-01-06 11:11:35 +0800196 private static final String EX_PORT_KEY = "exPortKey";
lishuai6c56f5e2015-11-17 16:38:19 +0800197 private static final String IFACEID = "ifaceid";
198 private static final String CONTROLLER_IP_KEY = "ipaddress";
199 public static final String DRIVER_NAME = "onosfw";
lishuai7dc63d92015-11-27 17:15:25 +0800200 private static final String VIRTUALPORT = "vtn-virtual-port";
lishuai6c56f5e2015-11-17 16:38:19 +0800201 private static final String SWITCHES_OF_CONTROLLER = "switchesOfController";
202 private static final String SWITCH_OF_LOCAL_HOST_PORTS = "switchOfLocalHostPorts";
lishuai8798bbe2016-05-05 16:02:03 +0800203 private static final String ROUTERINF_FLAG_OF_TENANTROUTER = "routerInfFlagOfTenantRouter";
lishuai858efd32015-12-04 14:30:36 +0800204 private static final String HOSTS_OF_SUBNET = "hostsOfSubnet";
205 private static final String EX_PORT_OF_DEVICE = "exPortOfDevice";
lishuaib43dbf72016-01-06 11:11:35 +0800206 private static final String EX_PORT_MAP = "exPortMap";
jiangruic69a7fd2015-11-19 15:40:01 +0800207 private static final String DEFAULT_IP = "0.0.0.0";
lishuai858efd32015-12-04 14:30:36 +0800208 private static final int SUBNET_NUM = 2;
lishuai6c56f5e2015-11-17 16:38:19 +0800209
lishuai7dc63d92015-11-27 17:15:25 +0800210 private EventuallyConsistentMap<VirtualPortId, VirtualPort> vPortStore;
lishuai6c56f5e2015-11-17 16:38:19 +0800211 private EventuallyConsistentMap<IpAddress, Boolean> switchesOfController;
jiangruic69a7fd2015-11-19 15:40:01 +0800212 private EventuallyConsistentMap<DeviceId, NetworkOfLocalHostPorts> switchOfLocalHostPorts;
lishuai858efd32015-12-04 14:30:36 +0800213 private EventuallyConsistentMap<SubnetId, Map<HostId, Host>> hostsOfSubnet;
lishuai8798bbe2016-05-05 16:02:03 +0800214 private EventuallyConsistentMap<TenantRouter, Boolean> routerInfFlagOfTenantRouter;
lishuai858efd32015-12-04 14:30:36 +0800215 private EventuallyConsistentMap<DeviceId, Port> exPortOfDevice;
lishuaib43dbf72016-01-06 11:11:35 +0800216 private static ConsistentMap<String, String> exPortMap;
lishuai6c56f5e2015-11-17 16:38:19 +0800217
218 @Activate
219 public void activate() {
220 appId = coreService.registerApplication(APP_ID);
221 classifierService = new ClassifierServiceImpl(appId);
222 l2ForwardService = new L2ForwardServiceImpl(appId);
lishuai74f2d532015-12-10 17:03:34 +0800223 arpService = new ArpServiceImpl(appId);
224 l3ForwardService = new L3ForwardServiceImpl(appId);
225 snatService = new SnatServiceImpl(appId);
226 dnatService = new DnatServiceImpl(appId);
lishuai6c56f5e2015-11-17 16:38:19 +0800227
228 deviceService.addListener(deviceListener);
229 hostService.addListener(hostListener);
lishuai74f2d532015-12-10 17:03:34 +0800230 vtnRscService.addListener(l3EventListener);
lishuai6c56f5e2015-11-17 16:38:19 +0800231
232 KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
233 .register(KryoNamespaces.API)
234 .register(NetworkOfLocalHostPorts.class)
235 .register(TenantNetworkId.class)
236 .register(Host.class)
237 .register(TenantNetwork.class)
238 .register(TenantId.class)
lishuai7dc63d92015-11-27 17:15:25 +0800239 .register(SubnetId.class)
240 .register(VirtualPortId.class)
241 .register(VirtualPort.State.class)
242 .register(AllowedAddressPair.class)
243 .register(FixedIp.class)
244 .register(BindingHostId.class)
245 .register(SecurityGroup.class)
246 .register(IpAddress.class)
247 .register(DefaultVirtualPort.class);
248
249 vPortStore = storageService
250 .<VirtualPortId, VirtualPort>eventuallyConsistentMapBuilder()
251 .withName(VIRTUALPORT).withSerializer(serializer)
252 .withTimestampProvider((k, v) -> clockService.getTimestamp())
253 .build();
lishuai6c56f5e2015-11-17 16:38:19 +0800254
255 switchesOfController = storageService
256 .<IpAddress, Boolean>eventuallyConsistentMapBuilder()
257 .withName(SWITCHES_OF_CONTROLLER).withSerializer(serializer)
258 .withTimestampProvider((k, v) -> clockService.getTimestamp())
259 .build();
260
261 switchOfLocalHostPorts = storageService
jiangruic69a7fd2015-11-19 15:40:01 +0800262 .<DeviceId, NetworkOfLocalHostPorts>eventuallyConsistentMapBuilder()
263 .withName(SWITCH_OF_LOCAL_HOST_PORTS).withSerializer(serializer)
264 .withTimestampProvider((k, v) -> clockService.getTimestamp())
lishuai6c56f5e2015-11-17 16:38:19 +0800265 .build();
266
lishuai858efd32015-12-04 14:30:36 +0800267 hostsOfSubnet = storageService
268 .<SubnetId, Map<HostId, Host>>eventuallyConsistentMapBuilder()
269 .withName(HOSTS_OF_SUBNET).withSerializer(serializer)
270 .withTimestampProvider((k, v) -> clockService.getTimestamp())
271 .build();
272
lishuai8798bbe2016-05-05 16:02:03 +0800273 routerInfFlagOfTenantRouter = storageService
274 .<TenantRouter, Boolean>eventuallyConsistentMapBuilder()
275 .withName(ROUTERINF_FLAG_OF_TENANTROUTER).withSerializer(serializer)
lishuai858efd32015-12-04 14:30:36 +0800276 .withTimestampProvider((k, v) -> clockService.getTimestamp())
277 .build();
278
279 exPortOfDevice = storageService
280 .<DeviceId, Port>eventuallyConsistentMapBuilder()
281 .withName(EX_PORT_OF_DEVICE).withSerializer(serializer)
282 .withTimestampProvider((k, v) -> clockService.getTimestamp())
283 .build();
284
lishuaib43dbf72016-01-06 11:11:35 +0800285 exPortMap = storageService
286 .<String, String>consistentMapBuilder()
287 .withName(EX_PORT_MAP)
288 .withApplicationId(appId)
289 .withPurgeOnUninstall()
290 .withSerializer(Serializer.using(Arrays.asList(KryoNamespaces.API)))
291 .build();
292
lishuai6c56f5e2015-11-17 16:38:19 +0800293 log.info("Started");
294 }
295
296 @Deactivate
297 public void deactivate() {
298 deviceService.removeListener(deviceListener);
299 hostService.removeListener(hostListener);
lishuai858efd32015-12-04 14:30:36 +0800300 vtnRscService.removeListener(l3EventListener);
lishuai6c56f5e2015-11-17 16:38:19 +0800301 log.info("Stopped");
302 }
303
304 @Override
305 public void onControllerDetected(Device controllerDevice) {
306 if (controllerDevice == null) {
307 log.error("The controller device is null");
308 return;
309 }
310 String localIpAddress = controllerDevice.annotations()
311 .value(CONTROLLER_IP_KEY);
312 IpAddress localIp = IpAddress.valueOf(localIpAddress);
313 DeviceId controllerDeviceId = controllerDevice.id();
314 DriverHandler handler = driverService.createHandler(controllerDeviceId);
315 if (mastershipService.isLocalMaster(controllerDeviceId)) {
316 // Get DataPathIdGenerator
317 String ipaddress = controllerDevice.annotations().value("ipaddress");
318 DataPathIdGenerator dpidGenerator = DataPathIdGenerator.builder()
319 .addIpAddress(ipaddress).build();
320 DeviceId deviceId = dpidGenerator.getDeviceId();
321 String dpid = dpidGenerator.getDpId();
322 // Inject pipeline driver name
323 BasicDeviceConfig config = configService.addConfig(deviceId,
324 BasicDeviceConfig.class);
325 config.driver(DRIVER_NAME);
326 configService.applyConfig(deviceId, BasicDeviceConfig.class, config.node());
327 // Add Bridge
lishuaib43dbf72016-01-06 11:11:35 +0800328 Versioned<String> exPortVersioned = exPortMap.get(EX_PORT_KEY);
329 if (exPortVersioned != null) {
330 VtnConfig.applyBridgeConfig(handler, dpid, exPortVersioned.value());
331 log.info("A new ovs is created in node {}", localIp.toString());
332 }
lishuai6c56f5e2015-11-17 16:38:19 +0800333 switchesOfController.put(localIp, true);
334 }
335 // Create tunnel in br-int on all controllers
336 programTunnelConfig(controllerDeviceId, localIp, handler);
337 }
338
339 @Override
340 public void onControllerVanished(Device controllerDevice) {
341 if (controllerDevice == null) {
342 log.error("The device is null");
343 return;
344 }
345 String dstIp = controllerDevice.annotations().value(CONTROLLER_IP_KEY);
346 IpAddress dstIpAddress = IpAddress.valueOf(dstIp);
347 DeviceId controllerDeviceId = controllerDevice.id();
348 if (mastershipService.isLocalMaster(controllerDeviceId)) {
349 switchesOfController.remove(dstIpAddress);
350 }
lishuai6c56f5e2015-11-17 16:38:19 +0800351 }
352
353 @Override
354 public void onOvsDetected(Device device) {
355 // Create tunnel out flow rules
356 applyTunnelOut(device, Objective.Operation.ADD);
357 }
358
359 @Override
360 public void onOvsVanished(Device device) {
361 // Remove Tunnel out flow rules
362 applyTunnelOut(device, Objective.Operation.REMOVE);
363 }
364
365 @Override
366 public void onHostDetected(Host host) {
lishuai858efd32015-12-04 14:30:36 +0800367 DeviceId deviceId = host.location().deviceId();
368 if (!mastershipService.isLocalMaster(deviceId)) {
369 return;
370 }
371 String ifaceId = host.annotations().value(IFACEID);
372 if (ifaceId == null) {
373 log.error("The ifaceId of Host is null");
374 return;
375 }
lishuaib43dbf72016-01-06 11:11:35 +0800376 programSffAndClassifierHost(host, Objective.Operation.ADD);
lishuai6c56f5e2015-11-17 16:38:19 +0800377 // apply L2 openflow rules
378 applyHostMonitoredL2Rules(host, Objective.Operation.ADD);
lishuai858efd32015-12-04 14:30:36 +0800379 // apply L3 openflow rules
380 applyHostMonitoredL3Rules(host, Objective.Operation.ADD);
lishuai6c56f5e2015-11-17 16:38:19 +0800381 }
382
383 @Override
384 public void onHostVanished(Host host) {
lishuai858efd32015-12-04 14:30:36 +0800385 DeviceId deviceId = host.location().deviceId();
386 if (!mastershipService.isLocalMaster(deviceId)) {
387 return;
388 }
389 String ifaceId = host.annotations().value(IFACEID);
390 if (ifaceId == null) {
391 log.error("The ifaceId of Host is null");
392 return;
393 }
lishuaib43dbf72016-01-06 11:11:35 +0800394 programSffAndClassifierHost(host, Objective.Operation.REMOVE);
lishuai6c56f5e2015-11-17 16:38:19 +0800395 // apply L2 openflow rules
396 applyHostMonitoredL2Rules(host, Objective.Operation.REMOVE);
lishuai858efd32015-12-04 14:30:36 +0800397 // apply L3 openflow rules
398 applyHostMonitoredL3Rules(host, Objective.Operation.REMOVE);
lishuai590d93a2015-12-11 13:05:14 +0800399 VirtualPortId virtualPortId = VirtualPortId.portId(ifaceId);
400 vPortStore.remove(virtualPortId);
lishuai6c56f5e2015-11-17 16:38:19 +0800401 }
402
403 private void programTunnelConfig(DeviceId localDeviceId, IpAddress localIp,
404 DriverHandler localHandler) {
jiangruic69a7fd2015-11-19 15:40:01 +0800405 if (mastershipService.isLocalMaster(localDeviceId)) {
406 VtnConfig.applyTunnelConfig(localHandler, localIp, IpAddress.valueOf(DEFAULT_IP));
407 log.info("Add tunnel on {}", localIp);
408 }
lishuai6c56f5e2015-11-17 16:38:19 +0800409 }
410
411 private void applyTunnelOut(Device device, Objective.Operation type) {
412 if (device == null) {
413 log.error("The device is null");
414 return;
415 }
416 if (!mastershipService.isLocalMaster(device.id())) {
417 return;
418 }
419 String controllerIp = VtnData.getControllerIpOfSwitch(device);
420 if (controllerIp == null) {
421 log.error("Can't find controller of device: {}",
422 device.id().toString());
423 return;
424 }
425 IpAddress ipAddress = IpAddress.valueOf(controllerIp);
426 if (!switchesOfController.containsKey(ipAddress)) {
427 log.error("Can't find controller of device: {}",
428 device.id().toString());
429 return;
430 }
431 if (type == Objective.Operation.ADD) {
lishuaia3e32342015-12-07 10:59:17 +0800432 // Save external port
433 Port export = getExPort(device.id());
lishuaid6f0c9e2015-12-16 11:40:01 +0800434 if (export != null) {
435 exPortOfDevice.put(device.id(), export);
436 }
lishuai6c56f5e2015-11-17 16:38:19 +0800437 switchOfLocalHostPorts.put(device.id(), new NetworkOfLocalHostPorts());
438 } else if (type == Objective.Operation.REMOVE) {
lishuaia3e32342015-12-07 10:59:17 +0800439 exPortOfDevice.remove(device.id());
lishuai6c56f5e2015-11-17 16:38:19 +0800440 switchOfLocalHostPorts.remove(device.id());
441 }
442 Iterable<Device> devices = deviceService.getAvailableDevices();
443 DeviceId localControllerId = VtnData.getControllerId(device, devices);
444 DriverHandler handler = driverService.createHandler(localControllerId);
445 Set<PortNumber> ports = VtnConfig.getPortNumbers(handler);
446 Iterable<Host> allHosts = hostService.getHosts();
jiangruic69a7fd2015-11-19 15:40:01 +0800447 String tunnelName = "vxlan-" + DEFAULT_IP;
lishuai6c56f5e2015-11-17 16:38:19 +0800448 if (allHosts != null) {
449 Sets.newHashSet(allHosts).stream().forEach(host -> {
450 MacAddress hostMac = host.mac();
451 String ifaceId = host.annotations().value(IFACEID);
452 if (ifaceId == null) {
453 log.error("The ifaceId of Host is null");
454 return;
455 }
456 VirtualPortId virtualPortId = VirtualPortId.portId(ifaceId);
457 VirtualPort virtualPort = virtualPortService
458 .getPort(virtualPortId);
459 TenantNetwork network = tenantNetworkService
460 .getNetwork(virtualPort.networkId());
461 SegmentationId segmentationId = network.segmentationId();
462 DeviceId remoteDeviceId = host.location().deviceId();
463 Device remoteDevice = deviceService.getDevice(remoteDeviceId);
464 String remoteControllerIp = VtnData
465 .getControllerIpOfSwitch(remoteDevice);
466 if (remoteControllerIp == null) {
467 log.error("Can't find remote controller of device: {}",
468 remoteDeviceId.toString());
469 return;
470 }
471 IpAddress remoteIpAddress = IpAddress
472 .valueOf(remoteControllerIp);
lishuai6c56f5e2015-11-17 16:38:19 +0800473 ports.stream()
474 .filter(p -> p.name().equalsIgnoreCase(tunnelName))
475 .forEach(p -> {
476 l2ForwardService
477 .programTunnelOut(device.id(), segmentationId, p,
jiangruic69a7fd2015-11-19 15:40:01 +0800478 hostMac, type, remoteIpAddress);
lishuai6c56f5e2015-11-17 16:38:19 +0800479 });
480 });
481 }
482 }
483
lishuaib43dbf72016-01-06 11:11:35 +0800484 private void programSffAndClassifierHost(Host host, Objective.Operation type) {
485 DeviceId deviceId = host.location().deviceId();
486 String ifaceId = host.annotations().value(IFACEID);
487 VirtualPortId virtualPortId = VirtualPortId.portId(ifaceId);
488 VirtualPort virtualPort = virtualPortService.getPort(virtualPortId);
489 if (virtualPort == null) {
490 virtualPort = VtnData.getPort(vPortStore, virtualPortId);
491 }
492 TenantId tenantId = virtualPort.tenantId();
493 if (Objective.Operation.ADD == type) {
494 vtnRscService.addDeviceIdOfOvsMap(virtualPortId, tenantId, deviceId);
495 } else if (Objective.Operation.REMOVE == type) {
496 vtnRscService.removeDeviceIdOfOvsMap(host, tenantId, deviceId);
497 }
498 }
499
lishuai6c56f5e2015-11-17 16:38:19 +0800500 private void applyHostMonitoredL2Rules(Host host, Objective.Operation type) {
501 DeviceId deviceId = host.location().deviceId();
502 if (!mastershipService.isLocalMaster(deviceId)) {
503 return;
504 }
505 String ifaceId = host.annotations().value(IFACEID);
506 if (ifaceId == null) {
507 log.error("The ifaceId of Host is null");
508 return;
509 }
510 VirtualPortId virtualPortId = VirtualPortId.portId(ifaceId);
511 VirtualPort virtualPort = virtualPortService.getPort(virtualPortId);
512 if (virtualPort == null) {
lishuai858efd32015-12-04 14:30:36 +0800513 virtualPort = VtnData.getPort(vPortStore, virtualPortId);
lishuai6c56f5e2015-11-17 16:38:19 +0800514 }
lishuai74f2d532015-12-10 17:03:34 +0800515 Iterator<FixedIp> fixip = virtualPort.fixedIps().iterator();
516 SubnetId subnetId = null;
517 if (fixip.hasNext()) {
518 subnetId = fixip.next().subnetId();
519 }
520 if (subnetId != null) {
521 Map<HostId, Host> hosts = new ConcurrentHashMap();
522 if (hostsOfSubnet.get(subnetId) != null) {
523 hosts = hostsOfSubnet.get(subnetId);
524 }
525 if (type == Objective.Operation.ADD) {
526 hosts.put(host.id(), host);
527 hostsOfSubnet.put(subnetId, hosts);
528 } else if (type == Objective.Operation.REMOVE) {
529 hosts.remove(host.id());
530 if (hosts.size() != 0) {
531 hostsOfSubnet.put(subnetId, hosts);
532 } else {
533 hostsOfSubnet.remove(subnetId);
534 }
535 }
536 }
lishuai6c56f5e2015-11-17 16:38:19 +0800537
538 Iterable<Device> devices = deviceService.getAvailableDevices();
539 PortNumber inPort = host.location().port();
540 MacAddress mac = host.mac();
541 Device device = deviceService.getDevice(deviceId);
542 String controllerIp = VtnData.getControllerIpOfSwitch(device);
543 IpAddress ipAddress = IpAddress.valueOf(controllerIp);
544 TenantNetwork network = tenantNetworkService.getNetwork(virtualPort.networkId());
545 if (network == null) {
546 log.error("Can't find network of the host");
547 return;
548 }
549 SegmentationId segmentationId = network.segmentationId();
550 // Get all the tunnel PortNumber in the current node
551 Iterable<Port> ports = deviceService.getPorts(deviceId);
552 Collection<PortNumber> localTunnelPorts = VtnData.getLocalTunnelPorts(ports);
553 // Get all the local vm's PortNumber in the current node
554 Map<TenantNetworkId, Set<PortNumber>> localHostPorts = switchOfLocalHostPorts
jiangruic69a7fd2015-11-19 15:40:01 +0800555 .get(deviceId).getNetworkOfLocalHostPorts();
lishuai6c56f5e2015-11-17 16:38:19 +0800556 Set<PortNumber> networkOflocalHostPorts = localHostPorts.get(network.id());
jiangruic69a7fd2015-11-19 15:40:01 +0800557 for (PortNumber p : localTunnelPorts) {
558 programGroupTable(deviceId, appId, p, devices, type);
559 }
lishuai6c56f5e2015-11-17 16:38:19 +0800560
561 if (type == Objective.Operation.ADD) {
lishuai7dc63d92015-11-27 17:15:25 +0800562 vPortStore.put(virtualPortId, virtualPort);
lishuai6c56f5e2015-11-17 16:38:19 +0800563 if (networkOflocalHostPorts == null) {
564 networkOflocalHostPorts = new HashSet<PortNumber>();
565 localHostPorts.putIfAbsent(network.id(), networkOflocalHostPorts);
566 }
567 networkOflocalHostPorts.add(inPort);
jiangruic69a7fd2015-11-19 15:40:01 +0800568 l2ForwardService.programLocalBcastRules(deviceId, segmentationId,
569 inPort, networkOflocalHostPorts,
570 localTunnelPorts,
571 type);
lishuai6c56f5e2015-11-17 16:38:19 +0800572 classifierService.programTunnelIn(deviceId, segmentationId,
573 localTunnelPorts,
574 type);
575 } else if (type == Objective.Operation.REMOVE) {
jiangruic69a7fd2015-11-19 15:40:01 +0800576 if (networkOflocalHostPorts != null) {
577 l2ForwardService.programLocalBcastRules(deviceId, segmentationId,
578 inPort, networkOflocalHostPorts,
579 localTunnelPorts,
580 type);
581 networkOflocalHostPorts.remove(inPort);
582 if (networkOflocalHostPorts.isEmpty()) {
583 classifierService.programTunnelIn(deviceId, segmentationId,
584 localTunnelPorts,
585 type);
586 switchOfLocalHostPorts.get(deviceId).getNetworkOfLocalHostPorts()
587 .remove(virtualPort.networkId());
588 }
lishuai6c56f5e2015-11-17 16:38:19 +0800589 }
590 }
591
jiangruic69a7fd2015-11-19 15:40:01 +0800592 l2ForwardService.programLocalOut(deviceId, segmentationId, inPort, mac,
593 type);
594
lishuai6c56f5e2015-11-17 16:38:19 +0800595 l2ForwardService.programTunnelBcastRules(deviceId, segmentationId,
596 networkOflocalHostPorts,
597 localTunnelPorts,
598 type);
599
600 programTunnelOuts(devices, ipAddress, segmentationId, mac,
601 type);
602
603 classifierService.programLocalIn(deviceId, segmentationId, inPort, mac,
604 appId, type);
605 }
606
607 private void programTunnelOuts(Iterable<Device> devices,
608 IpAddress ipAddress,
609 SegmentationId segmentationId,
610 MacAddress dstMac,
611 Objective.Operation type) {
jiangruic69a7fd2015-11-19 15:40:01 +0800612 String tunnelName = "vxlan-" + DEFAULT_IP;
lishuai6c56f5e2015-11-17 16:38:19 +0800613 Sets.newHashSet(devices).stream()
jiangruic69a7fd2015-11-19 15:40:01 +0800614 .filter(d -> d.type() == Device.Type.CONTROLLER)
615 .filter(d -> !("ovsdb:" + ipAddress).equals(d.id().toString()))
616 .forEach(d -> {
lishuai6c56f5e2015-11-17 16:38:19 +0800617 DriverHandler handler = driverService.createHandler(d.id());
618 BridgeConfig bridgeConfig = handler
619 .behaviour(BridgeConfig.class);
620 Collection<BridgeDescription> bridgeDescriptions = bridgeConfig
621 .getBridges();
lishuai6c56f5e2015-11-17 16:38:19 +0800622 Iterator<BridgeDescription> it = bridgeDescriptions
623 .iterator();
lishuai70304d12015-12-14 17:15:26 +0800624 while (it.hasNext()) {
lishuai6c56f5e2015-11-17 16:38:19 +0800625 BridgeDescription sw = it.next();
lishuai70304d12015-12-14 17:15:26 +0800626 if (sw.bridgeName().name().equals(VtnConfig.DEFAULT_BRIDGE_NAME)) {
627 List<Port> ports = deviceService.getPorts(sw.deviceId());
628 ports.stream()
629 .filter(p -> p.annotations().value(AnnotationKeys.PORT_NAME)
630 .equalsIgnoreCase(tunnelName))
631 .forEach(p -> {
632 l2ForwardService.programTunnelOut(sw.deviceId(),
633 segmentationId, p.number(),
634 dstMac, type, ipAddress);
635 });
636 break;
637 }
lishuai6c56f5e2015-11-17 16:38:19 +0800638 }
639 });
640 }
641
642 private class InnerDeviceListener implements DeviceListener {
643
644 @Override
645 public void event(DeviceEvent event) {
646 Device device = event.subject();
647 if (Device.Type.CONTROLLER == device.type()) {
648 if (DeviceEvent.Type.DEVICE_ADDED == event.type()) {
649 onControllerDetected(device);
650 }
651 if (DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED == event.type()) {
652 if (deviceService.isAvailable(device.id())) {
653 onControllerDetected(device);
654 } else {
655 onControllerVanished(device);
656 }
657 }
658 } else if (Device.Type.SWITCH == device.type()) {
659 if (DeviceEvent.Type.DEVICE_ADDED == event.type()) {
660 onOvsDetected(device);
661 }
662 if (DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED == event.type()) {
663 if (deviceService.isAvailable(device.id())) {
664 onOvsDetected(device);
665 } else {
666 onOvsVanished(device);
667 }
668 }
669 } else {
670 log.info("Do nothing for this device type");
671 }
672 }
673 }
674
675 private class InnerHostListener implements HostListener {
676
677 @Override
678 public void event(HostEvent event) {
679 Host host = event.subject();
680 if (HostEvent.Type.HOST_ADDED == event.type()) {
681 onHostDetected(host);
682 } else if (HostEvent.Type.HOST_REMOVED == event.type()) {
683 onHostVanished(host);
684 } else if (HostEvent.Type.HOST_UPDATED == event.type()) {
685 onHostVanished(host);
686 onHostDetected(host);
687 }
688 }
689
690 }
691
692 // Local Host Ports of Network.
693 private class NetworkOfLocalHostPorts {
694 private final Map<TenantNetworkId, Set<PortNumber>> networkOfLocalHostPorts =
695 new HashMap<TenantNetworkId, Set<PortNumber>>();
696
697 public Map<TenantNetworkId, Set<PortNumber>> getNetworkOfLocalHostPorts() {
698 return networkOfLocalHostPorts;
699 }
700 }
701
jiangruic69a7fd2015-11-19 15:40:01 +0800702 private void programGroupTable(DeviceId deviceId, ApplicationId appid,
703 PortNumber portNumber, Iterable<Device> devices, Objective.Operation type) {
704 if (type.equals(Objective.Operation.REMOVE)) {
705 return;
706 }
707
708 List<GroupBucket> buckets = Lists.newArrayList();
709 Sets.newHashSet(devices)
710 .stream()
711 .filter(d -> d.type() == Device.Type.CONTROLLER)
712 .filter(d -> !deviceId.equals(d.id()))
713 .forEach(d -> {
714 String ipAddress = d.annotations()
715 .value(CONTROLLER_IP_KEY);
716 Ip4Address dst = Ip4Address.valueOf(ipAddress);
717 Builder builder = DefaultTrafficTreatment.builder();
718
719 DriverHandler handler = driverService.createHandler(deviceId);
720 ExtensionTreatmentResolver resolver = handler.behaviour(ExtensionTreatmentResolver.class);
721 ExtensionTreatment treatment = resolver.getExtensionInstruction(NICIRA_SET_TUNNEL_DST.type());
722 try {
723 treatment.setPropertyValue("tunnelDst", dst);
724 } catch (Exception e) {
725 log.error("Failed to get extension instruction to set tunnel dst {}", deviceId);
726 }
727
728 builder.extension(treatment, deviceId);
729 builder.setOutput(portNumber);
730 GroupBucket bucket = DefaultGroupBucket
731 .createAllGroupBucket(builder.build());
732 buckets.add(bucket);
733 });
734 final GroupKey key = new DefaultGroupKey(APP_ID.getBytes());
735 GroupDescription groupDescription = new DefaultGroupDescription(deviceId,
736 GroupDescription.Type.ALL,
737 new GroupBuckets(buckets),
738 key,
739 L2ForwardServiceImpl.GROUP_ID,
740 appid);
741 groupService.addGroup(groupDescription);
742 }
lishuai858efd32015-12-04 14:30:36 +0800743
744 private class VtnL3EventListener implements VtnRscListener {
745 @Override
746 public void event(VtnRscEvent event) {
747 VtnRscEventFeedback l3Feedback = event.subject();
748 if (VtnRscEvent.Type.ROUTER_INTERFACE_PUT == event.type()) {
749 onRouterInterfaceDetected(l3Feedback);
750 } else
751 if (VtnRscEvent.Type.ROUTER_INTERFACE_DELETE == event.type()) {
752 onRouterInterfaceVanished(l3Feedback);
lishuai762df812016-01-08 11:51:15 +0800753 } else if (VtnRscEvent.Type.FLOATINGIP_BIND == event.type()) {
lishuai858efd32015-12-04 14:30:36 +0800754 onFloatingIpDetected(l3Feedback);
lishuai762df812016-01-08 11:51:15 +0800755 } else if (VtnRscEvent.Type.FLOATINGIP_UNBIND == event.type()) {
lishuai858efd32015-12-04 14:30:36 +0800756 onFloatingIpVanished(l3Feedback);
757 }
758 }
759
760 }
761
762 @Override
763 public void onRouterInterfaceDetected(VtnRscEventFeedback l3Feedback) {
764 Objective.Operation operation = Objective.Operation.ADD;
765 RouterInterface routerInf = l3Feedback.routerInterface();
lishuai762df812016-01-08 11:51:15 +0800766 VirtualPort gwPort = virtualPortService.getPort(routerInf.portId());
767 vPortStore.put(gwPort.portId(), gwPort);
lishuai858efd32015-12-04 14:30:36 +0800768 Iterable<RouterInterface> interfaces = routerInterfaceService
769 .getRouterInterfaces();
lishuai8798bbe2016-05-05 16:02:03 +0800770 Set<RouterInterface> interfacesSet = Sets.newHashSet(interfaces).stream()
771 .filter(r -> r.tenantId().equals(routerInf.tenantId()))
772 .filter(r -> r.routerId().equals(routerInf.routerId()))
lishuai858efd32015-12-04 14:30:36 +0800773 .collect(Collectors.toSet());
lishuai8798bbe2016-05-05 16:02:03 +0800774 TenantRouter tenantRouter = TenantRouter
775 .tenantRouter(routerInf.tenantId(), routerInf.routerId());
776 if (routerInfFlagOfTenantRouter.get(tenantRouter) != null) {
lishuai858efd32015-12-04 14:30:36 +0800777 programRouterInterface(routerInf, operation);
778 } else {
779 if (interfacesSet.size() >= SUBNET_NUM) {
780 programInterfacesSet(interfacesSet, operation);
781 }
782 }
783 }
784
785 @Override
786 public void onRouterInterfaceVanished(VtnRscEventFeedback l3Feedback) {
787 Objective.Operation operation = Objective.Operation.REMOVE;
788 RouterInterface routerInf = l3Feedback.routerInterface();
789 Iterable<RouterInterface> interfaces = routerInterfaceService
790 .getRouterInterfaces();
791 Set<RouterInterface> interfacesSet = Sets.newHashSet(interfaces)
792 .stream().filter(r -> r.tenantId().equals(routerInf.tenantId()))
793 .collect(Collectors.toSet());
lishuai8798bbe2016-05-05 16:02:03 +0800794 TenantRouter tenantRouter = TenantRouter
795 .tenantRouter(routerInf.tenantId(), routerInf.routerId());
796 if (routerInfFlagOfTenantRouter.get(tenantRouter) != null) {
lishuai858efd32015-12-04 14:30:36 +0800797 programRouterInterface(routerInf, operation);
798 if (interfacesSet.size() == 1) {
lishuai8798bbe2016-05-05 16:02:03 +0800799 routerInfFlagOfTenantRouter.remove(tenantRouter);
lishuai858efd32015-12-04 14:30:36 +0800800 interfacesSet.stream().forEach(r -> {
801 programRouterInterface(r, operation);
802 });
803 }
804 }
lishuai762df812016-01-08 11:51:15 +0800805 VirtualPort gwPort = virtualPortService.getPort(routerInf.portId());
806 if (gwPort == null) {
807 gwPort = VtnData.getPort(vPortStore, routerInf.portId());
808 }
809 vPortStore.remove(gwPort.portId());
lishuai858efd32015-12-04 14:30:36 +0800810 }
811
812 @Override
813 public void onFloatingIpDetected(VtnRscEventFeedback l3Feedback) {
lishuai762df812016-01-08 11:51:15 +0800814 programFloatingIpEvent(l3Feedback, VtnRscEvent.Type.FLOATINGIP_BIND);
lishuai858efd32015-12-04 14:30:36 +0800815 }
816
817 @Override
818 public void onFloatingIpVanished(VtnRscEventFeedback l3Feedback) {
lishuai762df812016-01-08 11:51:15 +0800819 programFloatingIpEvent(l3Feedback, VtnRscEvent.Type.FLOATINGIP_UNBIND);
lishuai858efd32015-12-04 14:30:36 +0800820 }
821
822 private void programInterfacesSet(Set<RouterInterface> interfacesSet,
823 Objective.Operation operation) {
824 int subnetVmNum = 0;
825 for (RouterInterface r : interfacesSet) {
826 // Get all the host of the subnet
827 Map<HostId, Host> hosts = hostsOfSubnet.get(r.subnetId());
lishuaid6f0c9e2015-12-16 11:40:01 +0800828 if (hosts != null && hosts.size() > 0) {
lishuai858efd32015-12-04 14:30:36 +0800829 subnetVmNum++;
830 if (subnetVmNum >= SUBNET_NUM) {
lishuai8798bbe2016-05-05 16:02:03 +0800831 TenantRouter tenantRouter = TenantRouter
832 .tenantRouter(r.tenantId(), r.routerId());
833 routerInfFlagOfTenantRouter.put(tenantRouter, true);
lishuai858efd32015-12-04 14:30:36 +0800834 interfacesSet.stream().forEach(f -> {
835 programRouterInterface(f, operation);
836 });
837 break;
838 }
839 }
840 }
841 }
842
843 private void programRouterInterface(RouterInterface routerInf,
844 Objective.Operation operation) {
lishuai8798bbe2016-05-05 16:02:03 +0800845 TenantRouter tenantRouter = TenantRouter
846 .tenantRouter(routerInf.tenantId(), routerInf.routerId());
847 SegmentationId l3vni = vtnRscService.getL3vni(tenantRouter);
lishuai858efd32015-12-04 14:30:36 +0800848 // Get all the host of the subnet
849 Map<HostId, Host> hosts = hostsOfSubnet.get(routerInf.subnetId());
850 hosts.values().stream().forEach(h -> {
851 applyEastWestL3Flows(h, l3vni, operation);
852 });
853 }
854
855 private void applyEastWestL3Flows(Host h, SegmentationId l3vni,
856 Objective.Operation operation) {
857 if (!mastershipService.isLocalMaster(h.location().deviceId())) {
858 log.debug("not master device:{}", h.location().deviceId());
859 return;
860 }
861 String ifaceId = h.annotations().value(IFACEID);
862 VirtualPort hPort = virtualPortService
863 .getPort(VirtualPortId.portId(ifaceId));
864 if (hPort == null) {
865 hPort = VtnData.getPort(vPortStore, VirtualPortId.portId(ifaceId));
866 }
867 IpAddress srcIp = null;
868 IpAddress srcGwIp = null;
869 MacAddress srcVmGwMac = null;
870 SubnetId srcSubnetId = null;
871 Iterator<FixedIp> srcIps = hPort.fixedIps().iterator();
872 if (srcIps.hasNext()) {
873 FixedIp fixedIp = srcIps.next();
874 srcIp = fixedIp.ip();
875 srcSubnetId = fixedIp.subnetId();
876 srcGwIp = subnetService.getSubnet(srcSubnetId).gatewayIp();
877 FixedIp fixedGwIp = FixedIp.fixedIp(srcSubnetId, srcGwIp);
878 VirtualPort gwPort = virtualPortService.getPort(fixedGwIp);
879 if (gwPort == null) {
880 gwPort = VtnData.getPort(vPortStore, fixedGwIp);
881 }
882 srcVmGwMac = gwPort.macAddress();
883 }
884 TenantNetwork network = tenantNetworkService
885 .getNetwork(hPort.networkId());
886 // Classifier rules
887 classifierService
888 .programL3InPortClassifierRules(h.location().deviceId(),
889 h.location().port(), h.mac(),
890 srcVmGwMac, l3vni, operation);
891 // Arp rules
892 if (operation == Objective.Operation.ADD) {
893 classifierService.programArpClassifierRules(h.location().deviceId(),
894 srcGwIp,
895 network.segmentationId(),
896 operation);
897 DriverHandler handler = driverService.createHandler(h.location().deviceId());
898 arpService.programArpRules(handler, h.location().deviceId(), srcGwIp,
899 network.segmentationId(), srcVmGwMac,
900 operation);
901 }
902 Iterable<Device> devices = deviceService.getAvailableDevices();
903 IpAddress srcArpIp = srcIp;
904 MacAddress srcArpGwMac = srcVmGwMac;
905 Sets.newHashSet(devices).stream()
906 .filter(d -> Device.Type.SWITCH == d.type()).forEach(d -> {
907 // L3FWD rules
908 l3ForwardService.programRouteRules(d.id(), l3vni, srcArpIp,
909 network.segmentationId(),
910 srcArpGwMac, h.mac(),
911 operation);
912 });
913 }
914
915 private void programFloatingIpEvent(VtnRscEventFeedback l3Feedback,
916 VtnRscEvent.Type type) {
917 FloatingIp floaingIp = l3Feedback.floatingIp();
918 if (floaingIp != null) {
919 VirtualPortId vmPortId = floaingIp.portId();
920 VirtualPort vmPort = virtualPortService.getPort(vmPortId);
921 VirtualPort fipPort = virtualPortService
922 .getPort(floaingIp.networkId(), floaingIp.floatingIp());
923 if (vmPort == null) {
924 vmPort = VtnData.getPort(vPortStore, vmPortId);
925 }
926 if (fipPort == null) {
927 fipPort = VtnData.getPort(vPortStore, floaingIp.networkId(),
928 floaingIp.floatingIp());
929 }
930 Set<Host> hostSet = hostService.getHostsByMac(vmPort.macAddress());
931 Host host = null;
932 for (Host h : hostSet) {
933 String ifaceid = h.annotations().value(IFACEID);
934 if (ifaceid != null && ifaceid.equals(vmPortId.portId())) {
935 host = h;
936 break;
937 }
938 }
939 if (host != null && vmPort != null && fipPort != null) {
940 DeviceId deviceId = host.location().deviceId();
941 Port exPort = exPortOfDevice.get(deviceId);
lishuai8798bbe2016-05-05 16:02:03 +0800942 TenantRouter tenantRouter = TenantRouter
943 .tenantRouter(floaingIp.tenantId(), floaingIp.routerId());
944 SegmentationId l3vni = vtnRscService.getL3vni(tenantRouter);
lishuai858efd32015-12-04 14:30:36 +0800945 // Floating ip BIND
lishuai762df812016-01-08 11:51:15 +0800946 if (type == VtnRscEvent.Type.FLOATINGIP_BIND) {
lishuai16c05af2016-01-21 18:39:05 +0800947 vPortStore.put(fipPort.portId(), fipPort);
lishuai858efd32015-12-04 14:30:36 +0800948 applyNorthSouthL3Flows(deviceId, host, vmPort, fipPort,
949 floaingIp, l3vni, exPort,
950 Objective.Operation.ADD);
lishuai762df812016-01-08 11:51:15 +0800951 } else if (type == VtnRscEvent.Type.FLOATINGIP_UNBIND) {
lishuai858efd32015-12-04 14:30:36 +0800952 // Floating ip UNBIND
953 applyNorthSouthL3Flows(deviceId, host, vmPort, fipPort,
954 floaingIp, l3vni, exPort,
955 Objective.Operation.REMOVE);
lishuai16c05af2016-01-21 18:39:05 +0800956 vPortStore.remove(fipPort.portId());
lishuai858efd32015-12-04 14:30:36 +0800957 }
958 }
959 }
960 }
961
962 private void applyNorthSouthL3Flows(DeviceId deviceId, Host host,
963 VirtualPort vmPort, VirtualPort fipPort,
964 FloatingIp floatingIp,
lishuai8798bbe2016-05-05 16:02:03 +0800965 SegmentationId l3vni, Port exPort,
lishuai858efd32015-12-04 14:30:36 +0800966 Objective.Operation operation) {
967 if (!mastershipService.isLocalMaster(deviceId)) {
968 log.debug("not master device:{}", deviceId);
969 return;
970 }
971 List gwIpMac = getGwIpAndMac(vmPort);
972 IpAddress dstVmGwIp = (IpAddress) gwIpMac.get(0);
973 MacAddress dstVmGwMac = (MacAddress) gwIpMac.get(1);
lishuai74f2d532015-12-10 17:03:34 +0800974 List fGwIpMac = getGwIpAndMac(fipPort);
975 MacAddress fGwMac = (MacAddress) fGwIpMac.get(1);
lishuai858efd32015-12-04 14:30:36 +0800976 TenantNetwork vmNetwork = tenantNetworkService
977 .getNetwork(vmPort.networkId());
978 TenantNetwork fipNetwork = tenantNetworkService
979 .getNetwork(fipPort.networkId());
980 // L3 downlink traffic flow
lishuaia3e32342015-12-07 10:59:17 +0800981 MacAddress exPortMac = MacAddress.valueOf(exPort.annotations()
982 .value(AnnotationKeys.PORT_MAC));
lishuai858efd32015-12-04 14:30:36 +0800983 classifierService.programArpClassifierRules(deviceId, floatingIp.floatingIp(),
984 fipNetwork.segmentationId(),
985 operation);
986 classifierService.programL3ExPortClassifierRules(deviceId, exPort.number(),
987 floatingIp.floatingIp(), operation);
988 DriverHandler handler = driverService.createHandler(deviceId);
989 arpService.programArpRules(handler, deviceId, floatingIp.floatingIp(),
990 fipNetwork.segmentationId(), exPortMac,
991 operation);
992 dnatService.programRules(deviceId, floatingIp.floatingIp(),
993 fGwMac, floatingIp.fixedIp(),
lishuai8798bbe2016-05-05 16:02:03 +0800994 l3vni, operation);
lishuai858efd32015-12-04 14:30:36 +0800995 l3ForwardService
lishuai8798bbe2016-05-05 16:02:03 +0800996 .programRouteRules(deviceId, l3vni, floatingIp.fixedIp(),
lishuai858efd32015-12-04 14:30:36 +0800997 vmNetwork.segmentationId(), dstVmGwMac,
998 vmPort.macAddress(), operation);
999
1000 // L3 uplink traffic flow
1001 classifierService.programL3InPortClassifierRules(deviceId,
1002 host.location().port(),
1003 host.mac(), dstVmGwMac,
lishuai8798bbe2016-05-05 16:02:03 +08001004 l3vni, operation);
1005 snatService.programRules(deviceId, l3vni, floatingIp.fixedIp(),
lishuai858efd32015-12-04 14:30:36 +08001006 fGwMac, exPortMac,
1007 floatingIp.floatingIp(),
1008 fipNetwork.segmentationId(), operation);
1009 if (operation == Objective.Operation.ADD) {
1010 classifierService.programArpClassifierRules(deviceId, dstVmGwIp,
1011 vmNetwork.segmentationId(),
1012 operation);
1013 arpService.programArpRules(handler, deviceId, dstVmGwIp,
1014 vmNetwork.segmentationId(), dstVmGwMac,
1015 operation);
1016 l2ForwardService.programLocalOut(deviceId,
1017 fipNetwork.segmentationId(),
1018 exPort.number(), fGwMac, operation);
1019 }
1020 }
1021
1022 private Port getExPort(DeviceId deviceId) {
1023 List<Port> ports = deviceService.getPorts(deviceId);
1024 Port exPort = null;
1025 for (Port port : ports) {
1026 String portName = port.annotations().value(AnnotationKeys.PORT_NAME);
lishuaib43dbf72016-01-06 11:11:35 +08001027 Versioned<String> exPortVersioned = exPortMap.get(EX_PORT_KEY);
1028 if (portName != null && exPortVersioned != null && portName.
1029 equals(exPortVersioned.value())) {
lishuai858efd32015-12-04 14:30:36 +08001030 exPort = port;
1031 break;
1032 }
1033 }
1034 return exPort;
1035 }
1036
1037 private List getGwIpAndMac(VirtualPort port) {
1038 List list = new ArrayList();
1039 MacAddress gwMac = null;
1040 SubnetId subnetId = null;
1041 IpAddress gwIp = null;
1042 Iterator<FixedIp> fixips = port.fixedIps().iterator();
1043 if (fixips.hasNext()) {
1044 FixedIp fixip = fixips.next();
1045 subnetId = fixip.subnetId();
1046 gwIp = subnetService.getSubnet(subnetId).gatewayIp();
1047 FixedIp fixedGwIp = FixedIp.fixedIp(fixip.subnetId(), gwIp);
1048 VirtualPort gwPort = virtualPortService.getPort(fixedGwIp);
1049 if (gwPort == null) {
1050 gwPort = VtnData.getPort(vPortStore, fixedGwIp);
1051 }
1052 gwMac = gwPort.macAddress();
1053 }
1054 list.add(gwIp);
1055 list.add(gwMac);
1056 return list;
1057 }
1058
lishuai858efd32015-12-04 14:30:36 +08001059 private void applyHostMonitoredL3Rules(Host host,
1060 Objective.Operation operation) {
1061 String ifaceId = host.annotations().value(IFACEID);
1062 DeviceId deviceId = host.location().deviceId();
1063 VirtualPortId portId = VirtualPortId.portId(ifaceId);
1064 VirtualPort port = virtualPortService.getPort(portId);
1065 if (port == null) {
1066 port = VtnData.getPort(vPortStore, portId);
1067 }
1068 TenantId tenantId = port.tenantId();
1069 Port exPort = exPortOfDevice.get(deviceId);
lishuai858efd32015-12-04 14:30:36 +08001070 Iterator<FixedIp> fixips = port.fixedIps().iterator();
1071 SubnetId sid = null;
1072 IpAddress hostIp = null;
1073 if (fixips.hasNext()) {
1074 FixedIp fixip = fixips.next();
1075 sid = fixip.subnetId();
1076 hostIp = fixip.ip();
1077 }
1078 final SubnetId subnetId = sid;
1079 // L3 internal network access to each other
1080 Iterable<RouterInterface> interfaces = routerInterfaceService
1081 .getRouterInterfaces();
lishuai8798bbe2016-05-05 16:02:03 +08001082 Set<RouterInterface> hostInterfaces = Sets.newHashSet(interfaces)
lishuai858efd32015-12-04 14:30:36 +08001083 .stream().filter(r -> r.tenantId().equals(tenantId))
lishuai8798bbe2016-05-05 16:02:03 +08001084 .filter(r -> r.subnetId().equals(subnetId))
lishuai858efd32015-12-04 14:30:36 +08001085 .collect(Collectors.toSet());
lishuai8798bbe2016-05-05 16:02:03 +08001086 hostInterfaces.stream().forEach(routerInf -> {
1087 Set<RouterInterface> interfacesSet = Sets.newHashSet(interfaces)
1088 .stream().filter(r -> r.tenantId().equals(tenantId))
1089 .filter(r -> r.routerId().equals(routerInf.routerId()))
1090 .collect(Collectors.toSet());
1091 long count = interfacesSet.stream()
1092 .filter(r -> !r.subnetId().equals(subnetId)).count();
1093 if (count > 0) {
1094 TenantRouter tenantRouter = TenantRouter
1095 .tenantRouter(routerInf.tenantId(), routerInf.routerId());
1096 SegmentationId l3vni = vtnRscService.getL3vni(tenantRouter);
1097 if (operation == Objective.Operation.ADD) {
1098 if (routerInfFlagOfTenantRouter.get(tenantRouter) != null) {
1099 applyEastWestL3Flows(host, l3vni, operation);
1100 } else {
1101 if (interfacesSet.size() > 1) {
1102 programInterfacesSet(interfacesSet, operation);
1103 }
1104 }
1105 } else if (operation == Objective.Operation.REMOVE) {
1106 if (routerInfFlagOfTenantRouter.get(tenantRouter) != null) {
1107 applyEastWestL3Flows(host, l3vni, operation);
lishuai858efd32015-12-04 14:30:36 +08001108 }
1109 }
lishuai858efd32015-12-04 14:30:36 +08001110 }
lishuai8798bbe2016-05-05 16:02:03 +08001111 });
lishuai858efd32015-12-04 14:30:36 +08001112 // L3 external and internal network access to each other
1113 FloatingIp floatingIp = null;
1114 Iterable<FloatingIp> floatingIps = floatingIpService.getFloatingIps();
1115 Set<FloatingIp> floatingIpSet = Sets.newHashSet(floatingIps).stream()
1116 .filter(f -> f.tenantId().equals(tenantId))
1117 .collect(Collectors.toSet());
1118 for (FloatingIp f : floatingIpSet) {
1119 IpAddress fixedIp = f.fixedIp();
1120 if (fixedIp.equals(hostIp)) {
1121 floatingIp = f;
1122 break;
1123 }
1124 }
1125 if (floatingIp != null) {
lishuai8798bbe2016-05-05 16:02:03 +08001126 TenantRouter tenantRouter = TenantRouter
1127 .tenantRouter(floatingIp.tenantId(), floatingIp.routerId());
1128 SegmentationId l3vni = vtnRscService.getL3vni(tenantRouter);
lishuai858efd32015-12-04 14:30:36 +08001129 VirtualPort fipPort = virtualPortService
1130 .getPort(floatingIp.networkId(), floatingIp.floatingIp());
1131 if (fipPort == null) {
1132 fipPort = VtnData.getPort(vPortStore, floatingIp.networkId(),
1133 floatingIp.floatingIp());
1134 }
1135 applyNorthSouthL3Flows(deviceId, host, port, fipPort, floatingIp,
1136 l3vni, exPort, operation);
1137 }
1138 }
lishuai74f2d532015-12-10 17:03:34 +08001139
1140 public static void setExPortName(String name) {
lishuaib43dbf72016-01-06 11:11:35 +08001141 exPortMap.put(EX_PORT_KEY, name);
lishuai74f2d532015-12-10 17:03:34 +08001142 }
lishuai6c56f5e2015-11-17 16:38:19 +08001143}