blob: be3d2692ba9919e566e0905eb6141a4ae4595f81 [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;
Wu wenbinacc10ea2016-05-06 16:48:56 +0800109import org.onosproject.vtnrsc.Subnet;
lishuai6c56f5e2015-11-17 16:38:19 +0800110import org.onosproject.vtnrsc.SubnetId;
111import org.onosproject.vtnrsc.TenantId;
112import org.onosproject.vtnrsc.TenantNetwork;
113import org.onosproject.vtnrsc.TenantNetworkId;
lishuai8798bbe2016-05-05 16:02:03 +0800114import org.onosproject.vtnrsc.TenantRouter;
lishuai6c56f5e2015-11-17 16:38:19 +0800115import org.onosproject.vtnrsc.VirtualPort;
116import org.onosproject.vtnrsc.VirtualPortId;
lishuai858efd32015-12-04 14:30:36 +0800117import org.onosproject.vtnrsc.event.VtnRscEvent;
118import org.onosproject.vtnrsc.event.VtnRscEventFeedback;
119import org.onosproject.vtnrsc.event.VtnRscListener;
120import org.onosproject.vtnrsc.floatingip.FloatingIpService;
lishuai858efd32015-12-04 14:30:36 +0800121import org.onosproject.vtnrsc.routerinterface.RouterInterfaceService;
122import org.onosproject.vtnrsc.service.VtnRscService;
123import org.onosproject.vtnrsc.subnet.SubnetService;
lishuai6c56f5e2015-11-17 16:38:19 +0800124import org.onosproject.vtnrsc.tenantnetwork.TenantNetworkService;
125import org.onosproject.vtnrsc.virtualport.VirtualPortService;
126import org.slf4j.Logger;
127
jiangruic69a7fd2015-11-19 15:40:01 +0800128import com.google.common.collect.Lists;
lishuai6c56f5e2015-11-17 16:38:19 +0800129import com.google.common.collect.Sets;
130
131/**
132 * Provides implementation of VTNService.
133 */
134@Component(immediate = true)
135@Service
Jonathan Hart51539b82015-10-29 09:53:04 -0700136public class VtnManager implements VtnService {
lishuai6c56f5e2015-11-17 16:38:19 +0800137 private final Logger log = getLogger(getClass());
138 private static final String APP_ID = "org.onosproject.app.vtn";
139
140 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
141 protected NetworkConfigService configService;
142
143 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
144 protected DeviceService deviceService;
145
146 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
147 protected HostService hostService;
148
149 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
150 protected CoreService coreService;
151
152 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
153 protected StorageService storageService;
154
155 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
156 protected TenantNetworkService tenantNetworkService;
157
158 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
159 protected VirtualPortService virtualPortService;
160
161 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
162 protected DriverService driverService;
163
164 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
165 protected LogicalClockService clockService;
166
167 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
168 protected MastershipService mastershipService;
169
jiangruic69a7fd2015-11-19 15:40:01 +0800170 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
171 protected GroupService groupService;
172
lishuai858efd32015-12-04 14:30:36 +0800173 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
174 protected SubnetService subnetService;
175
176 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
177 protected VtnRscService vtnRscService;
178
179 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
180 protected FloatingIpService floatingIpService;
181
182 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
lishuai858efd32015-12-04 14:30:36 +0800183 protected RouterInterfaceService routerInterfaceService;
184
lishuai6c56f5e2015-11-17 16:38:19 +0800185 private ApplicationId appId;
186 private ClassifierService classifierService;
187 private L2ForwardService l2ForwardService;
lishuai858efd32015-12-04 14:30:36 +0800188 private ArpService arpService;
189 private L3ForwardService l3ForwardService;
190 private SnatService snatService;
191 private DnatService dnatService;
lishuai6c56f5e2015-11-17 16:38:19 +0800192
193 private final HostListener hostListener = new InnerHostListener();
194 private final DeviceListener deviceListener = new InnerDeviceListener();
lishuai858efd32015-12-04 14:30:36 +0800195 private final VtnRscListener l3EventListener = new VtnL3EventListener();
lishuai6c56f5e2015-11-17 16:38:19 +0800196
lishuaib43dbf72016-01-06 11:11:35 +0800197 private static final String EX_PORT_KEY = "exPortKey";
lishuai6c56f5e2015-11-17 16:38:19 +0800198 private static final String IFACEID = "ifaceid";
199 private static final String CONTROLLER_IP_KEY = "ipaddress";
200 public static final String DRIVER_NAME = "onosfw";
lishuai7dc63d92015-11-27 17:15:25 +0800201 private static final String VIRTUALPORT = "vtn-virtual-port";
lishuai6c56f5e2015-11-17 16:38:19 +0800202 private static final String SWITCHES_OF_CONTROLLER = "switchesOfController";
203 private static final String SWITCH_OF_LOCAL_HOST_PORTS = "switchOfLocalHostPorts";
lishuai8798bbe2016-05-05 16:02:03 +0800204 private static final String ROUTERINF_FLAG_OF_TENANTROUTER = "routerInfFlagOfTenantRouter";
lishuai858efd32015-12-04 14:30:36 +0800205 private static final String HOSTS_OF_SUBNET = "hostsOfSubnet";
206 private static final String EX_PORT_OF_DEVICE = "exPortOfDevice";
lishuaib43dbf72016-01-06 11:11:35 +0800207 private static final String EX_PORT_MAP = "exPortMap";
jiangruic69a7fd2015-11-19 15:40:01 +0800208 private static final String DEFAULT_IP = "0.0.0.0";
Wu wenbinacc10ea2016-05-06 16:48:56 +0800209 private static final String USERDATA_IP = "169.254.169.254";
lishuai858efd32015-12-04 14:30:36 +0800210 private static final int SUBNET_NUM = 2;
lishuai6c56f5e2015-11-17 16:38:19 +0800211
lishuai7dc63d92015-11-27 17:15:25 +0800212 private EventuallyConsistentMap<VirtualPortId, VirtualPort> vPortStore;
lishuai6c56f5e2015-11-17 16:38:19 +0800213 private EventuallyConsistentMap<IpAddress, Boolean> switchesOfController;
jiangruic69a7fd2015-11-19 15:40:01 +0800214 private EventuallyConsistentMap<DeviceId, NetworkOfLocalHostPorts> switchOfLocalHostPorts;
lishuai858efd32015-12-04 14:30:36 +0800215 private EventuallyConsistentMap<SubnetId, Map<HostId, Host>> hostsOfSubnet;
lishuai8798bbe2016-05-05 16:02:03 +0800216 private EventuallyConsistentMap<TenantRouter, Boolean> routerInfFlagOfTenantRouter;
lishuai858efd32015-12-04 14:30:36 +0800217 private EventuallyConsistentMap<DeviceId, Port> exPortOfDevice;
lishuaib43dbf72016-01-06 11:11:35 +0800218 private static ConsistentMap<String, String> exPortMap;
lishuai6c56f5e2015-11-17 16:38:19 +0800219
220 @Activate
221 public void activate() {
222 appId = coreService.registerApplication(APP_ID);
223 classifierService = new ClassifierServiceImpl(appId);
224 l2ForwardService = new L2ForwardServiceImpl(appId);
lishuai74f2d532015-12-10 17:03:34 +0800225 arpService = new ArpServiceImpl(appId);
226 l3ForwardService = new L3ForwardServiceImpl(appId);
227 snatService = new SnatServiceImpl(appId);
228 dnatService = new DnatServiceImpl(appId);
lishuai6c56f5e2015-11-17 16:38:19 +0800229
230 deviceService.addListener(deviceListener);
231 hostService.addListener(hostListener);
lishuai74f2d532015-12-10 17:03:34 +0800232 vtnRscService.addListener(l3EventListener);
lishuai6c56f5e2015-11-17 16:38:19 +0800233
234 KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
235 .register(KryoNamespaces.API)
236 .register(NetworkOfLocalHostPorts.class)
237 .register(TenantNetworkId.class)
238 .register(Host.class)
239 .register(TenantNetwork.class)
240 .register(TenantId.class)
lishuai7dc63d92015-11-27 17:15:25 +0800241 .register(SubnetId.class)
242 .register(VirtualPortId.class)
243 .register(VirtualPort.State.class)
244 .register(AllowedAddressPair.class)
245 .register(FixedIp.class)
246 .register(BindingHostId.class)
247 .register(SecurityGroup.class)
248 .register(IpAddress.class)
249 .register(DefaultVirtualPort.class);
250
251 vPortStore = storageService
252 .<VirtualPortId, VirtualPort>eventuallyConsistentMapBuilder()
253 .withName(VIRTUALPORT).withSerializer(serializer)
254 .withTimestampProvider((k, v) -> clockService.getTimestamp())
255 .build();
lishuai6c56f5e2015-11-17 16:38:19 +0800256
257 switchesOfController = storageService
258 .<IpAddress, Boolean>eventuallyConsistentMapBuilder()
259 .withName(SWITCHES_OF_CONTROLLER).withSerializer(serializer)
260 .withTimestampProvider((k, v) -> clockService.getTimestamp())
261 .build();
262
263 switchOfLocalHostPorts = storageService
jiangruic69a7fd2015-11-19 15:40:01 +0800264 .<DeviceId, NetworkOfLocalHostPorts>eventuallyConsistentMapBuilder()
265 .withName(SWITCH_OF_LOCAL_HOST_PORTS).withSerializer(serializer)
266 .withTimestampProvider((k, v) -> clockService.getTimestamp())
lishuai6c56f5e2015-11-17 16:38:19 +0800267 .build();
268
lishuai858efd32015-12-04 14:30:36 +0800269 hostsOfSubnet = storageService
270 .<SubnetId, Map<HostId, Host>>eventuallyConsistentMapBuilder()
271 .withName(HOSTS_OF_SUBNET).withSerializer(serializer)
272 .withTimestampProvider((k, v) -> clockService.getTimestamp())
273 .build();
274
lishuai8798bbe2016-05-05 16:02:03 +0800275 routerInfFlagOfTenantRouter = storageService
276 .<TenantRouter, Boolean>eventuallyConsistentMapBuilder()
277 .withName(ROUTERINF_FLAG_OF_TENANTROUTER).withSerializer(serializer)
lishuai858efd32015-12-04 14:30:36 +0800278 .withTimestampProvider((k, v) -> clockService.getTimestamp())
279 .build();
280
281 exPortOfDevice = storageService
282 .<DeviceId, Port>eventuallyConsistentMapBuilder()
283 .withName(EX_PORT_OF_DEVICE).withSerializer(serializer)
284 .withTimestampProvider((k, v) -> clockService.getTimestamp())
285 .build();
286
lishuaib43dbf72016-01-06 11:11:35 +0800287 exPortMap = storageService
288 .<String, String>consistentMapBuilder()
289 .withName(EX_PORT_MAP)
290 .withApplicationId(appId)
291 .withPurgeOnUninstall()
292 .withSerializer(Serializer.using(Arrays.asList(KryoNamespaces.API)))
293 .build();
294
lishuai6c56f5e2015-11-17 16:38:19 +0800295 log.info("Started");
296 }
297
298 @Deactivate
299 public void deactivate() {
300 deviceService.removeListener(deviceListener);
301 hostService.removeListener(hostListener);
lishuai858efd32015-12-04 14:30:36 +0800302 vtnRscService.removeListener(l3EventListener);
lishuai6c56f5e2015-11-17 16:38:19 +0800303 log.info("Stopped");
304 }
305
306 @Override
307 public void onControllerDetected(Device controllerDevice) {
308 if (controllerDevice == null) {
309 log.error("The controller device is null");
310 return;
311 }
312 String localIpAddress = controllerDevice.annotations()
313 .value(CONTROLLER_IP_KEY);
314 IpAddress localIp = IpAddress.valueOf(localIpAddress);
315 DeviceId controllerDeviceId = controllerDevice.id();
316 DriverHandler handler = driverService.createHandler(controllerDeviceId);
317 if (mastershipService.isLocalMaster(controllerDeviceId)) {
318 // Get DataPathIdGenerator
319 String ipaddress = controllerDevice.annotations().value("ipaddress");
320 DataPathIdGenerator dpidGenerator = DataPathIdGenerator.builder()
321 .addIpAddress(ipaddress).build();
322 DeviceId deviceId = dpidGenerator.getDeviceId();
323 String dpid = dpidGenerator.getDpId();
324 // Inject pipeline driver name
325 BasicDeviceConfig config = configService.addConfig(deviceId,
326 BasicDeviceConfig.class);
327 config.driver(DRIVER_NAME);
328 configService.applyConfig(deviceId, BasicDeviceConfig.class, config.node());
329 // Add Bridge
lishuaib43dbf72016-01-06 11:11:35 +0800330 Versioned<String> exPortVersioned = exPortMap.get(EX_PORT_KEY);
331 if (exPortVersioned != null) {
332 VtnConfig.applyBridgeConfig(handler, dpid, exPortVersioned.value());
333 log.info("A new ovs is created in node {}", localIp.toString());
334 }
lishuai6c56f5e2015-11-17 16:38:19 +0800335 switchesOfController.put(localIp, true);
336 }
337 // Create tunnel in br-int on all controllers
338 programTunnelConfig(controllerDeviceId, localIp, handler);
339 }
340
341 @Override
342 public void onControllerVanished(Device controllerDevice) {
343 if (controllerDevice == null) {
344 log.error("The device is null");
345 return;
346 }
347 String dstIp = controllerDevice.annotations().value(CONTROLLER_IP_KEY);
348 IpAddress dstIpAddress = IpAddress.valueOf(dstIp);
349 DeviceId controllerDeviceId = controllerDevice.id();
350 if (mastershipService.isLocalMaster(controllerDeviceId)) {
351 switchesOfController.remove(dstIpAddress);
352 }
lishuai6c56f5e2015-11-17 16:38:19 +0800353 }
354
355 @Override
356 public void onOvsDetected(Device device) {
357 // Create tunnel out flow rules
358 applyTunnelOut(device, Objective.Operation.ADD);
359 }
360
361 @Override
362 public void onOvsVanished(Device device) {
363 // Remove Tunnel out flow rules
364 applyTunnelOut(device, Objective.Operation.REMOVE);
365 }
366
367 @Override
368 public void onHostDetected(Host host) {
lishuai858efd32015-12-04 14:30:36 +0800369 DeviceId deviceId = host.location().deviceId();
370 if (!mastershipService.isLocalMaster(deviceId)) {
371 return;
372 }
373 String ifaceId = host.annotations().value(IFACEID);
374 if (ifaceId == null) {
375 log.error("The ifaceId of Host is null");
376 return;
377 }
lishuaib43dbf72016-01-06 11:11:35 +0800378 programSffAndClassifierHost(host, Objective.Operation.ADD);
lishuai6c56f5e2015-11-17 16:38:19 +0800379 // apply L2 openflow rules
380 applyHostMonitoredL2Rules(host, Objective.Operation.ADD);
lishuai858efd32015-12-04 14:30:36 +0800381 // apply L3 openflow rules
382 applyHostMonitoredL3Rules(host, Objective.Operation.ADD);
lishuai6c56f5e2015-11-17 16:38:19 +0800383 }
384
385 @Override
386 public void onHostVanished(Host host) {
lishuai858efd32015-12-04 14:30:36 +0800387 DeviceId deviceId = host.location().deviceId();
388 if (!mastershipService.isLocalMaster(deviceId)) {
389 return;
390 }
391 String ifaceId = host.annotations().value(IFACEID);
392 if (ifaceId == null) {
393 log.error("The ifaceId of Host is null");
394 return;
395 }
lishuaib43dbf72016-01-06 11:11:35 +0800396 programSffAndClassifierHost(host, Objective.Operation.REMOVE);
lishuai6c56f5e2015-11-17 16:38:19 +0800397 // apply L2 openflow rules
398 applyHostMonitoredL2Rules(host, Objective.Operation.REMOVE);
lishuai858efd32015-12-04 14:30:36 +0800399 // apply L3 openflow rules
400 applyHostMonitoredL3Rules(host, Objective.Operation.REMOVE);
lishuai590d93a2015-12-11 13:05:14 +0800401 VirtualPortId virtualPortId = VirtualPortId.portId(ifaceId);
402 vPortStore.remove(virtualPortId);
lishuai6c56f5e2015-11-17 16:38:19 +0800403 }
404
405 private void programTunnelConfig(DeviceId localDeviceId, IpAddress localIp,
406 DriverHandler localHandler) {
jiangruic69a7fd2015-11-19 15:40:01 +0800407 if (mastershipService.isLocalMaster(localDeviceId)) {
408 VtnConfig.applyTunnelConfig(localHandler, localIp, IpAddress.valueOf(DEFAULT_IP));
409 log.info("Add tunnel on {}", localIp);
410 }
lishuai6c56f5e2015-11-17 16:38:19 +0800411 }
412
413 private void applyTunnelOut(Device device, Objective.Operation type) {
414 if (device == null) {
415 log.error("The device is null");
416 return;
417 }
418 if (!mastershipService.isLocalMaster(device.id())) {
419 return;
420 }
421 String controllerIp = VtnData.getControllerIpOfSwitch(device);
422 if (controllerIp == null) {
423 log.error("Can't find controller of device: {}",
424 device.id().toString());
425 return;
426 }
427 IpAddress ipAddress = IpAddress.valueOf(controllerIp);
428 if (!switchesOfController.containsKey(ipAddress)) {
429 log.error("Can't find controller of device: {}",
430 device.id().toString());
431 return;
432 }
433 if (type == Objective.Operation.ADD) {
lishuaia3e32342015-12-07 10:59:17 +0800434 // Save external port
435 Port export = getExPort(device.id());
lishuaid6f0c9e2015-12-16 11:40:01 +0800436 if (export != null) {
437 exPortOfDevice.put(device.id(), export);
438 }
lishuai6c56f5e2015-11-17 16:38:19 +0800439 switchOfLocalHostPorts.put(device.id(), new NetworkOfLocalHostPorts());
440 } else if (type == Objective.Operation.REMOVE) {
lishuaia3e32342015-12-07 10:59:17 +0800441 exPortOfDevice.remove(device.id());
lishuai6c56f5e2015-11-17 16:38:19 +0800442 switchOfLocalHostPorts.remove(device.id());
443 }
444 Iterable<Device> devices = deviceService.getAvailableDevices();
445 DeviceId localControllerId = VtnData.getControllerId(device, devices);
446 DriverHandler handler = driverService.createHandler(localControllerId);
447 Set<PortNumber> ports = VtnConfig.getPortNumbers(handler);
448 Iterable<Host> allHosts = hostService.getHosts();
jiangruic69a7fd2015-11-19 15:40:01 +0800449 String tunnelName = "vxlan-" + DEFAULT_IP;
lishuai6c56f5e2015-11-17 16:38:19 +0800450 if (allHosts != null) {
451 Sets.newHashSet(allHosts).stream().forEach(host -> {
452 MacAddress hostMac = host.mac();
453 String ifaceId = host.annotations().value(IFACEID);
454 if (ifaceId == null) {
455 log.error("The ifaceId of Host is null");
456 return;
457 }
458 VirtualPortId virtualPortId = VirtualPortId.portId(ifaceId);
459 VirtualPort virtualPort = virtualPortService
460 .getPort(virtualPortId);
461 TenantNetwork network = tenantNetworkService
462 .getNetwork(virtualPort.networkId());
463 SegmentationId segmentationId = network.segmentationId();
464 DeviceId remoteDeviceId = host.location().deviceId();
465 Device remoteDevice = deviceService.getDevice(remoteDeviceId);
466 String remoteControllerIp = VtnData
467 .getControllerIpOfSwitch(remoteDevice);
468 if (remoteControllerIp == null) {
469 log.error("Can't find remote controller of device: {}",
470 remoteDeviceId.toString());
471 return;
472 }
473 IpAddress remoteIpAddress = IpAddress
474 .valueOf(remoteControllerIp);
lishuai6c56f5e2015-11-17 16:38:19 +0800475 ports.stream()
476 .filter(p -> p.name().equalsIgnoreCase(tunnelName))
477 .forEach(p -> {
478 l2ForwardService
479 .programTunnelOut(device.id(), segmentationId, p,
jiangruic69a7fd2015-11-19 15:40:01 +0800480 hostMac, type, remoteIpAddress);
lishuai6c56f5e2015-11-17 16:38:19 +0800481 });
482 });
483 }
484 }
485
lishuaib43dbf72016-01-06 11:11:35 +0800486 private void programSffAndClassifierHost(Host host, Objective.Operation type) {
487 DeviceId deviceId = host.location().deviceId();
488 String ifaceId = host.annotations().value(IFACEID);
489 VirtualPortId virtualPortId = VirtualPortId.portId(ifaceId);
490 VirtualPort virtualPort = virtualPortService.getPort(virtualPortId);
491 if (virtualPort == null) {
492 virtualPort = VtnData.getPort(vPortStore, virtualPortId);
493 }
494 TenantId tenantId = virtualPort.tenantId();
495 if (Objective.Operation.ADD == type) {
496 vtnRscService.addDeviceIdOfOvsMap(virtualPortId, tenantId, deviceId);
497 } else if (Objective.Operation.REMOVE == type) {
498 vtnRscService.removeDeviceIdOfOvsMap(host, tenantId, deviceId);
499 }
500 }
501
lishuai6c56f5e2015-11-17 16:38:19 +0800502 private void applyHostMonitoredL2Rules(Host host, Objective.Operation type) {
503 DeviceId deviceId = host.location().deviceId();
504 if (!mastershipService.isLocalMaster(deviceId)) {
505 return;
506 }
507 String ifaceId = host.annotations().value(IFACEID);
508 if (ifaceId == null) {
509 log.error("The ifaceId of Host is null");
510 return;
511 }
512 VirtualPortId virtualPortId = VirtualPortId.portId(ifaceId);
513 VirtualPort virtualPort = virtualPortService.getPort(virtualPortId);
514 if (virtualPort == null) {
lishuai858efd32015-12-04 14:30:36 +0800515 virtualPort = VtnData.getPort(vPortStore, virtualPortId);
lishuai6c56f5e2015-11-17 16:38:19 +0800516 }
lishuai74f2d532015-12-10 17:03:34 +0800517 Iterator<FixedIp> fixip = virtualPort.fixedIps().iterator();
518 SubnetId subnetId = null;
519 if (fixip.hasNext()) {
520 subnetId = fixip.next().subnetId();
521 }
522 if (subnetId != null) {
523 Map<HostId, Host> hosts = new ConcurrentHashMap();
524 if (hostsOfSubnet.get(subnetId) != null) {
525 hosts = hostsOfSubnet.get(subnetId);
526 }
527 if (type == Objective.Operation.ADD) {
528 hosts.put(host.id(), host);
529 hostsOfSubnet.put(subnetId, hosts);
530 } else if (type == Objective.Operation.REMOVE) {
531 hosts.remove(host.id());
532 if (hosts.size() != 0) {
533 hostsOfSubnet.put(subnetId, hosts);
534 } else {
535 hostsOfSubnet.remove(subnetId);
536 }
537 }
538 }
lishuai6c56f5e2015-11-17 16:38:19 +0800539
540 Iterable<Device> devices = deviceService.getAvailableDevices();
541 PortNumber inPort = host.location().port();
542 MacAddress mac = host.mac();
543 Device device = deviceService.getDevice(deviceId);
544 String controllerIp = VtnData.getControllerIpOfSwitch(device);
545 IpAddress ipAddress = IpAddress.valueOf(controllerIp);
546 TenantNetwork network = tenantNetworkService.getNetwork(virtualPort.networkId());
547 if (network == null) {
548 log.error("Can't find network of the host");
549 return;
550 }
551 SegmentationId segmentationId = network.segmentationId();
552 // Get all the tunnel PortNumber in the current node
553 Iterable<Port> ports = deviceService.getPorts(deviceId);
554 Collection<PortNumber> localTunnelPorts = VtnData.getLocalTunnelPorts(ports);
555 // Get all the local vm's PortNumber in the current node
556 Map<TenantNetworkId, Set<PortNumber>> localHostPorts = switchOfLocalHostPorts
jiangruic69a7fd2015-11-19 15:40:01 +0800557 .get(deviceId).getNetworkOfLocalHostPorts();
lishuai6c56f5e2015-11-17 16:38:19 +0800558 Set<PortNumber> networkOflocalHostPorts = localHostPorts.get(network.id());
jiangruic69a7fd2015-11-19 15:40:01 +0800559 for (PortNumber p : localTunnelPorts) {
560 programGroupTable(deviceId, appId, p, devices, type);
561 }
Wu wenbinacc10ea2016-05-06 16:48:56 +0800562 Subnet subnet = subnetService.getSubnet(subnetId);
563 String deviceOwner = virtualPort.deviceOwner();
564 if (deviceOwner != null) {
565 if (deviceOwner.equalsIgnoreCase("network:dhcp")) {
566 Sets.newHashSet(devices).stream()
567 .filter(d -> d.type() == Device.Type.SWITCH)
568 .forEach(d -> {
569 if (subnet != null) {
570 IpAddress dstIp = IpAddress
571 .valueOf(USERDATA_IP);
572 classifierService
573 .programUserdataClassifierRules(d.id(),
574 subnet.cidr(),
575 dstIp,
576 mac,
577 segmentationId,
578 type);
579 }
580 });
581 }
582 }
lishuai6c56f5e2015-11-17 16:38:19 +0800583 if (type == Objective.Operation.ADD) {
lishuai7dc63d92015-11-27 17:15:25 +0800584 vPortStore.put(virtualPortId, virtualPort);
lishuai6c56f5e2015-11-17 16:38:19 +0800585 if (networkOflocalHostPorts == null) {
586 networkOflocalHostPorts = new HashSet<PortNumber>();
587 localHostPorts.putIfAbsent(network.id(), networkOflocalHostPorts);
588 }
589 networkOflocalHostPorts.add(inPort);
jiangruic69a7fd2015-11-19 15:40:01 +0800590 l2ForwardService.programLocalBcastRules(deviceId, segmentationId,
591 inPort, networkOflocalHostPorts,
592 localTunnelPorts,
593 type);
lishuai6c56f5e2015-11-17 16:38:19 +0800594 classifierService.programTunnelIn(deviceId, segmentationId,
595 localTunnelPorts,
596 type);
597 } else if (type == Objective.Operation.REMOVE) {
jiangruic69a7fd2015-11-19 15:40:01 +0800598 if (networkOflocalHostPorts != null) {
599 l2ForwardService.programLocalBcastRules(deviceId, segmentationId,
600 inPort, networkOflocalHostPorts,
601 localTunnelPorts,
602 type);
603 networkOflocalHostPorts.remove(inPort);
604 if (networkOflocalHostPorts.isEmpty()) {
605 classifierService.programTunnelIn(deviceId, segmentationId,
606 localTunnelPorts,
607 type);
608 switchOfLocalHostPorts.get(deviceId).getNetworkOfLocalHostPorts()
609 .remove(virtualPort.networkId());
610 }
lishuai6c56f5e2015-11-17 16:38:19 +0800611 }
612 }
613
jiangruic69a7fd2015-11-19 15:40:01 +0800614 l2ForwardService.programLocalOut(deviceId, segmentationId, inPort, mac,
615 type);
616
lishuai6c56f5e2015-11-17 16:38:19 +0800617 l2ForwardService.programTunnelBcastRules(deviceId, segmentationId,
618 networkOflocalHostPorts,
619 localTunnelPorts,
620 type);
621
622 programTunnelOuts(devices, ipAddress, segmentationId, mac,
623 type);
624
625 classifierService.programLocalIn(deviceId, segmentationId, inPort, mac,
626 appId, type);
627 }
628
629 private void programTunnelOuts(Iterable<Device> devices,
630 IpAddress ipAddress,
631 SegmentationId segmentationId,
632 MacAddress dstMac,
633 Objective.Operation type) {
jiangruic69a7fd2015-11-19 15:40:01 +0800634 String tunnelName = "vxlan-" + DEFAULT_IP;
lishuai6c56f5e2015-11-17 16:38:19 +0800635 Sets.newHashSet(devices).stream()
jiangruic69a7fd2015-11-19 15:40:01 +0800636 .filter(d -> d.type() == Device.Type.CONTROLLER)
637 .filter(d -> !("ovsdb:" + ipAddress).equals(d.id().toString()))
638 .forEach(d -> {
lishuai6c56f5e2015-11-17 16:38:19 +0800639 DriverHandler handler = driverService.createHandler(d.id());
640 BridgeConfig bridgeConfig = handler
641 .behaviour(BridgeConfig.class);
642 Collection<BridgeDescription> bridgeDescriptions = bridgeConfig
643 .getBridges();
lishuai6c56f5e2015-11-17 16:38:19 +0800644 Iterator<BridgeDescription> it = bridgeDescriptions
645 .iterator();
lishuai70304d12015-12-14 17:15:26 +0800646 while (it.hasNext()) {
lishuai6c56f5e2015-11-17 16:38:19 +0800647 BridgeDescription sw = it.next();
lishuai70304d12015-12-14 17:15:26 +0800648 if (sw.bridgeName().name().equals(VtnConfig.DEFAULT_BRIDGE_NAME)) {
649 List<Port> ports = deviceService.getPorts(sw.deviceId());
650 ports.stream()
651 .filter(p -> p.annotations().value(AnnotationKeys.PORT_NAME)
652 .equalsIgnoreCase(tunnelName))
653 .forEach(p -> {
654 l2ForwardService.programTunnelOut(sw.deviceId(),
655 segmentationId, p.number(),
656 dstMac, type, ipAddress);
657 });
658 break;
659 }
lishuai6c56f5e2015-11-17 16:38:19 +0800660 }
661 });
662 }
663
664 private class InnerDeviceListener implements DeviceListener {
665
666 @Override
667 public void event(DeviceEvent event) {
668 Device device = event.subject();
669 if (Device.Type.CONTROLLER == device.type()) {
670 if (DeviceEvent.Type.DEVICE_ADDED == event.type()) {
671 onControllerDetected(device);
672 }
673 if (DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED == event.type()) {
674 if (deviceService.isAvailable(device.id())) {
675 onControllerDetected(device);
676 } else {
677 onControllerVanished(device);
678 }
679 }
680 } else if (Device.Type.SWITCH == device.type()) {
681 if (DeviceEvent.Type.DEVICE_ADDED == event.type()) {
682 onOvsDetected(device);
683 }
684 if (DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED == event.type()) {
685 if (deviceService.isAvailable(device.id())) {
686 onOvsDetected(device);
687 } else {
688 onOvsVanished(device);
689 }
690 }
691 } else {
692 log.info("Do nothing for this device type");
693 }
694 }
695 }
696
697 private class InnerHostListener implements HostListener {
698
699 @Override
700 public void event(HostEvent event) {
701 Host host = event.subject();
702 if (HostEvent.Type.HOST_ADDED == event.type()) {
703 onHostDetected(host);
704 } else if (HostEvent.Type.HOST_REMOVED == event.type()) {
705 onHostVanished(host);
706 } else if (HostEvent.Type.HOST_UPDATED == event.type()) {
707 onHostVanished(host);
708 onHostDetected(host);
709 }
710 }
711
712 }
713
714 // Local Host Ports of Network.
715 private class NetworkOfLocalHostPorts {
716 private final Map<TenantNetworkId, Set<PortNumber>> networkOfLocalHostPorts =
717 new HashMap<TenantNetworkId, Set<PortNumber>>();
718
719 public Map<TenantNetworkId, Set<PortNumber>> getNetworkOfLocalHostPorts() {
720 return networkOfLocalHostPorts;
721 }
722 }
723
jiangruic69a7fd2015-11-19 15:40:01 +0800724 private void programGroupTable(DeviceId deviceId, ApplicationId appid,
725 PortNumber portNumber, Iterable<Device> devices, Objective.Operation type) {
726 if (type.equals(Objective.Operation.REMOVE)) {
727 return;
728 }
729
730 List<GroupBucket> buckets = Lists.newArrayList();
731 Sets.newHashSet(devices)
732 .stream()
733 .filter(d -> d.type() == Device.Type.CONTROLLER)
734 .filter(d -> !deviceId.equals(d.id()))
735 .forEach(d -> {
736 String ipAddress = d.annotations()
737 .value(CONTROLLER_IP_KEY);
738 Ip4Address dst = Ip4Address.valueOf(ipAddress);
739 Builder builder = DefaultTrafficTreatment.builder();
740
741 DriverHandler handler = driverService.createHandler(deviceId);
742 ExtensionTreatmentResolver resolver = handler.behaviour(ExtensionTreatmentResolver.class);
743 ExtensionTreatment treatment = resolver.getExtensionInstruction(NICIRA_SET_TUNNEL_DST.type());
744 try {
745 treatment.setPropertyValue("tunnelDst", dst);
746 } catch (Exception e) {
747 log.error("Failed to get extension instruction to set tunnel dst {}", deviceId);
748 }
749
750 builder.extension(treatment, deviceId);
751 builder.setOutput(portNumber);
752 GroupBucket bucket = DefaultGroupBucket
753 .createAllGroupBucket(builder.build());
754 buckets.add(bucket);
755 });
756 final GroupKey key = new DefaultGroupKey(APP_ID.getBytes());
757 GroupDescription groupDescription = new DefaultGroupDescription(deviceId,
758 GroupDescription.Type.ALL,
759 new GroupBuckets(buckets),
760 key,
761 L2ForwardServiceImpl.GROUP_ID,
762 appid);
763 groupService.addGroup(groupDescription);
764 }
lishuai858efd32015-12-04 14:30:36 +0800765
766 private class VtnL3EventListener implements VtnRscListener {
767 @Override
768 public void event(VtnRscEvent event) {
769 VtnRscEventFeedback l3Feedback = event.subject();
770 if (VtnRscEvent.Type.ROUTER_INTERFACE_PUT == event.type()) {
771 onRouterInterfaceDetected(l3Feedback);
772 } else
773 if (VtnRscEvent.Type.ROUTER_INTERFACE_DELETE == event.type()) {
774 onRouterInterfaceVanished(l3Feedback);
lishuai762df812016-01-08 11:51:15 +0800775 } else if (VtnRscEvent.Type.FLOATINGIP_BIND == event.type()) {
lishuai858efd32015-12-04 14:30:36 +0800776 onFloatingIpDetected(l3Feedback);
lishuai762df812016-01-08 11:51:15 +0800777 } else if (VtnRscEvent.Type.FLOATINGIP_UNBIND == event.type()) {
lishuai858efd32015-12-04 14:30:36 +0800778 onFloatingIpVanished(l3Feedback);
779 }
780 }
781
782 }
783
784 @Override
785 public void onRouterInterfaceDetected(VtnRscEventFeedback l3Feedback) {
786 Objective.Operation operation = Objective.Operation.ADD;
787 RouterInterface routerInf = l3Feedback.routerInterface();
lishuai762df812016-01-08 11:51:15 +0800788 VirtualPort gwPort = virtualPortService.getPort(routerInf.portId());
789 vPortStore.put(gwPort.portId(), gwPort);
lishuai858efd32015-12-04 14:30:36 +0800790 Iterable<RouterInterface> interfaces = routerInterfaceService
791 .getRouterInterfaces();
lishuai8798bbe2016-05-05 16:02:03 +0800792 Set<RouterInterface> interfacesSet = Sets.newHashSet(interfaces).stream()
793 .filter(r -> r.tenantId().equals(routerInf.tenantId()))
794 .filter(r -> r.routerId().equals(routerInf.routerId()))
lishuai858efd32015-12-04 14:30:36 +0800795 .collect(Collectors.toSet());
lishuai8798bbe2016-05-05 16:02:03 +0800796 TenantRouter tenantRouter = TenantRouter
797 .tenantRouter(routerInf.tenantId(), routerInf.routerId());
798 if (routerInfFlagOfTenantRouter.get(tenantRouter) != null) {
lishuai858efd32015-12-04 14:30:36 +0800799 programRouterInterface(routerInf, operation);
800 } else {
801 if (interfacesSet.size() >= SUBNET_NUM) {
802 programInterfacesSet(interfacesSet, operation);
803 }
804 }
805 }
806
807 @Override
808 public void onRouterInterfaceVanished(VtnRscEventFeedback l3Feedback) {
809 Objective.Operation operation = Objective.Operation.REMOVE;
810 RouterInterface routerInf = l3Feedback.routerInterface();
811 Iterable<RouterInterface> interfaces = routerInterfaceService
812 .getRouterInterfaces();
813 Set<RouterInterface> interfacesSet = Sets.newHashSet(interfaces)
814 .stream().filter(r -> r.tenantId().equals(routerInf.tenantId()))
815 .collect(Collectors.toSet());
lishuai8798bbe2016-05-05 16:02:03 +0800816 TenantRouter tenantRouter = TenantRouter
817 .tenantRouter(routerInf.tenantId(), routerInf.routerId());
818 if (routerInfFlagOfTenantRouter.get(tenantRouter) != null) {
lishuai858efd32015-12-04 14:30:36 +0800819 programRouterInterface(routerInf, operation);
820 if (interfacesSet.size() == 1) {
lishuai8798bbe2016-05-05 16:02:03 +0800821 routerInfFlagOfTenantRouter.remove(tenantRouter);
lishuai858efd32015-12-04 14:30:36 +0800822 interfacesSet.stream().forEach(r -> {
823 programRouterInterface(r, operation);
824 });
825 }
826 }
lishuai762df812016-01-08 11:51:15 +0800827 VirtualPort gwPort = virtualPortService.getPort(routerInf.portId());
828 if (gwPort == null) {
829 gwPort = VtnData.getPort(vPortStore, routerInf.portId());
830 }
831 vPortStore.remove(gwPort.portId());
lishuai858efd32015-12-04 14:30:36 +0800832 }
833
834 @Override
835 public void onFloatingIpDetected(VtnRscEventFeedback l3Feedback) {
lishuai762df812016-01-08 11:51:15 +0800836 programFloatingIpEvent(l3Feedback, VtnRscEvent.Type.FLOATINGIP_BIND);
lishuai858efd32015-12-04 14:30:36 +0800837 }
838
839 @Override
840 public void onFloatingIpVanished(VtnRscEventFeedback l3Feedback) {
lishuai762df812016-01-08 11:51:15 +0800841 programFloatingIpEvent(l3Feedback, VtnRscEvent.Type.FLOATINGIP_UNBIND);
lishuai858efd32015-12-04 14:30:36 +0800842 }
843
844 private void programInterfacesSet(Set<RouterInterface> interfacesSet,
845 Objective.Operation operation) {
846 int subnetVmNum = 0;
847 for (RouterInterface r : interfacesSet) {
848 // Get all the host of the subnet
849 Map<HostId, Host> hosts = hostsOfSubnet.get(r.subnetId());
lishuaid6f0c9e2015-12-16 11:40:01 +0800850 if (hosts != null && hosts.size() > 0) {
lishuai858efd32015-12-04 14:30:36 +0800851 subnetVmNum++;
852 if (subnetVmNum >= SUBNET_NUM) {
lishuai8798bbe2016-05-05 16:02:03 +0800853 TenantRouter tenantRouter = TenantRouter
854 .tenantRouter(r.tenantId(), r.routerId());
855 routerInfFlagOfTenantRouter.put(tenantRouter, true);
lishuai858efd32015-12-04 14:30:36 +0800856 interfacesSet.stream().forEach(f -> {
857 programRouterInterface(f, operation);
858 });
859 break;
860 }
861 }
862 }
863 }
864
865 private void programRouterInterface(RouterInterface routerInf,
866 Objective.Operation operation) {
lishuai8798bbe2016-05-05 16:02:03 +0800867 TenantRouter tenantRouter = TenantRouter
868 .tenantRouter(routerInf.tenantId(), routerInf.routerId());
869 SegmentationId l3vni = vtnRscService.getL3vni(tenantRouter);
lishuai858efd32015-12-04 14:30:36 +0800870 // Get all the host of the subnet
871 Map<HostId, Host> hosts = hostsOfSubnet.get(routerInf.subnetId());
872 hosts.values().stream().forEach(h -> {
873 applyEastWestL3Flows(h, l3vni, operation);
874 });
875 }
876
877 private void applyEastWestL3Flows(Host h, SegmentationId l3vni,
878 Objective.Operation operation) {
879 if (!mastershipService.isLocalMaster(h.location().deviceId())) {
880 log.debug("not master device:{}", h.location().deviceId());
881 return;
882 }
883 String ifaceId = h.annotations().value(IFACEID);
884 VirtualPort hPort = virtualPortService
885 .getPort(VirtualPortId.portId(ifaceId));
886 if (hPort == null) {
887 hPort = VtnData.getPort(vPortStore, VirtualPortId.portId(ifaceId));
888 }
889 IpAddress srcIp = null;
890 IpAddress srcGwIp = null;
891 MacAddress srcVmGwMac = null;
892 SubnetId srcSubnetId = null;
893 Iterator<FixedIp> srcIps = hPort.fixedIps().iterator();
894 if (srcIps.hasNext()) {
895 FixedIp fixedIp = srcIps.next();
896 srcIp = fixedIp.ip();
897 srcSubnetId = fixedIp.subnetId();
898 srcGwIp = subnetService.getSubnet(srcSubnetId).gatewayIp();
899 FixedIp fixedGwIp = FixedIp.fixedIp(srcSubnetId, srcGwIp);
900 VirtualPort gwPort = virtualPortService.getPort(fixedGwIp);
901 if (gwPort == null) {
902 gwPort = VtnData.getPort(vPortStore, fixedGwIp);
903 }
904 srcVmGwMac = gwPort.macAddress();
905 }
906 TenantNetwork network = tenantNetworkService
907 .getNetwork(hPort.networkId());
908 // Classifier rules
909 classifierService
910 .programL3InPortClassifierRules(h.location().deviceId(),
911 h.location().port(), h.mac(),
912 srcVmGwMac, l3vni, operation);
913 // Arp rules
914 if (operation == Objective.Operation.ADD) {
915 classifierService.programArpClassifierRules(h.location().deviceId(),
916 srcGwIp,
917 network.segmentationId(),
918 operation);
919 DriverHandler handler = driverService.createHandler(h.location().deviceId());
920 arpService.programArpRules(handler, h.location().deviceId(), srcGwIp,
921 network.segmentationId(), srcVmGwMac,
922 operation);
923 }
924 Iterable<Device> devices = deviceService.getAvailableDevices();
925 IpAddress srcArpIp = srcIp;
926 MacAddress srcArpGwMac = srcVmGwMac;
927 Sets.newHashSet(devices).stream()
928 .filter(d -> Device.Type.SWITCH == d.type()).forEach(d -> {
929 // L3FWD rules
930 l3ForwardService.programRouteRules(d.id(), l3vni, srcArpIp,
931 network.segmentationId(),
932 srcArpGwMac, h.mac(),
933 operation);
934 });
935 }
936
937 private void programFloatingIpEvent(VtnRscEventFeedback l3Feedback,
938 VtnRscEvent.Type type) {
939 FloatingIp floaingIp = l3Feedback.floatingIp();
940 if (floaingIp != null) {
941 VirtualPortId vmPortId = floaingIp.portId();
942 VirtualPort vmPort = virtualPortService.getPort(vmPortId);
943 VirtualPort fipPort = virtualPortService
944 .getPort(floaingIp.networkId(), floaingIp.floatingIp());
945 if (vmPort == null) {
946 vmPort = VtnData.getPort(vPortStore, vmPortId);
947 }
948 if (fipPort == null) {
949 fipPort = VtnData.getPort(vPortStore, floaingIp.networkId(),
950 floaingIp.floatingIp());
951 }
952 Set<Host> hostSet = hostService.getHostsByMac(vmPort.macAddress());
953 Host host = null;
954 for (Host h : hostSet) {
955 String ifaceid = h.annotations().value(IFACEID);
956 if (ifaceid != null && ifaceid.equals(vmPortId.portId())) {
957 host = h;
958 break;
959 }
960 }
961 if (host != null && vmPort != null && fipPort != null) {
962 DeviceId deviceId = host.location().deviceId();
963 Port exPort = exPortOfDevice.get(deviceId);
lishuai8798bbe2016-05-05 16:02:03 +0800964 TenantRouter tenantRouter = TenantRouter
965 .tenantRouter(floaingIp.tenantId(), floaingIp.routerId());
966 SegmentationId l3vni = vtnRscService.getL3vni(tenantRouter);
lishuai858efd32015-12-04 14:30:36 +0800967 // Floating ip BIND
lishuai762df812016-01-08 11:51:15 +0800968 if (type == VtnRscEvent.Type.FLOATINGIP_BIND) {
lishuai16c05af2016-01-21 18:39:05 +0800969 vPortStore.put(fipPort.portId(), fipPort);
lishuai858efd32015-12-04 14:30:36 +0800970 applyNorthSouthL3Flows(deviceId, host, vmPort, fipPort,
971 floaingIp, l3vni, exPort,
972 Objective.Operation.ADD);
lishuai762df812016-01-08 11:51:15 +0800973 } else if (type == VtnRscEvent.Type.FLOATINGIP_UNBIND) {
lishuai858efd32015-12-04 14:30:36 +0800974 // Floating ip UNBIND
975 applyNorthSouthL3Flows(deviceId, host, vmPort, fipPort,
976 floaingIp, l3vni, exPort,
977 Objective.Operation.REMOVE);
lishuai16c05af2016-01-21 18:39:05 +0800978 vPortStore.remove(fipPort.portId());
lishuai858efd32015-12-04 14:30:36 +0800979 }
980 }
981 }
982 }
983
984 private void applyNorthSouthL3Flows(DeviceId deviceId, Host host,
985 VirtualPort vmPort, VirtualPort fipPort,
986 FloatingIp floatingIp,
lishuai8798bbe2016-05-05 16:02:03 +0800987 SegmentationId l3vni, Port exPort,
lishuai858efd32015-12-04 14:30:36 +0800988 Objective.Operation operation) {
989 if (!mastershipService.isLocalMaster(deviceId)) {
990 log.debug("not master device:{}", deviceId);
991 return;
992 }
993 List gwIpMac = getGwIpAndMac(vmPort);
994 IpAddress dstVmGwIp = (IpAddress) gwIpMac.get(0);
995 MacAddress dstVmGwMac = (MacAddress) gwIpMac.get(1);
lishuai74f2d532015-12-10 17:03:34 +0800996 List fGwIpMac = getGwIpAndMac(fipPort);
997 MacAddress fGwMac = (MacAddress) fGwIpMac.get(1);
lishuai858efd32015-12-04 14:30:36 +0800998 TenantNetwork vmNetwork = tenantNetworkService
999 .getNetwork(vmPort.networkId());
1000 TenantNetwork fipNetwork = tenantNetworkService
1001 .getNetwork(fipPort.networkId());
1002 // L3 downlink traffic flow
lishuaia3e32342015-12-07 10:59:17 +08001003 MacAddress exPortMac = MacAddress.valueOf(exPort.annotations()
1004 .value(AnnotationKeys.PORT_MAC));
lishuai858efd32015-12-04 14:30:36 +08001005 classifierService.programArpClassifierRules(deviceId, floatingIp.floatingIp(),
1006 fipNetwork.segmentationId(),
1007 operation);
1008 classifierService.programL3ExPortClassifierRules(deviceId, exPort.number(),
1009 floatingIp.floatingIp(), operation);
1010 DriverHandler handler = driverService.createHandler(deviceId);
1011 arpService.programArpRules(handler, deviceId, floatingIp.floatingIp(),
1012 fipNetwork.segmentationId(), exPortMac,
1013 operation);
1014 dnatService.programRules(deviceId, floatingIp.floatingIp(),
1015 fGwMac, floatingIp.fixedIp(),
lishuai8798bbe2016-05-05 16:02:03 +08001016 l3vni, operation);
lishuai858efd32015-12-04 14:30:36 +08001017 l3ForwardService
lishuai8798bbe2016-05-05 16:02:03 +08001018 .programRouteRules(deviceId, l3vni, floatingIp.fixedIp(),
lishuai858efd32015-12-04 14:30:36 +08001019 vmNetwork.segmentationId(), dstVmGwMac,
1020 vmPort.macAddress(), operation);
1021
1022 // L3 uplink traffic flow
1023 classifierService.programL3InPortClassifierRules(deviceId,
1024 host.location().port(),
1025 host.mac(), dstVmGwMac,
lishuai8798bbe2016-05-05 16:02:03 +08001026 l3vni, operation);
1027 snatService.programRules(deviceId, l3vni, floatingIp.fixedIp(),
lishuai858efd32015-12-04 14:30:36 +08001028 fGwMac, exPortMac,
1029 floatingIp.floatingIp(),
1030 fipNetwork.segmentationId(), operation);
1031 if (operation == Objective.Operation.ADD) {
1032 classifierService.programArpClassifierRules(deviceId, dstVmGwIp,
1033 vmNetwork.segmentationId(),
1034 operation);
1035 arpService.programArpRules(handler, deviceId, dstVmGwIp,
1036 vmNetwork.segmentationId(), dstVmGwMac,
1037 operation);
1038 l2ForwardService.programLocalOut(deviceId,
1039 fipNetwork.segmentationId(),
1040 exPort.number(), fGwMac, operation);
1041 }
1042 }
1043
1044 private Port getExPort(DeviceId deviceId) {
1045 List<Port> ports = deviceService.getPorts(deviceId);
1046 Port exPort = null;
1047 for (Port port : ports) {
1048 String portName = port.annotations().value(AnnotationKeys.PORT_NAME);
lishuaib43dbf72016-01-06 11:11:35 +08001049 Versioned<String> exPortVersioned = exPortMap.get(EX_PORT_KEY);
1050 if (portName != null && exPortVersioned != null && portName.
1051 equals(exPortVersioned.value())) {
lishuai858efd32015-12-04 14:30:36 +08001052 exPort = port;
1053 break;
1054 }
1055 }
1056 return exPort;
1057 }
1058
1059 private List getGwIpAndMac(VirtualPort port) {
1060 List list = new ArrayList();
1061 MacAddress gwMac = null;
1062 SubnetId subnetId = null;
1063 IpAddress gwIp = null;
1064 Iterator<FixedIp> fixips = port.fixedIps().iterator();
1065 if (fixips.hasNext()) {
1066 FixedIp fixip = fixips.next();
1067 subnetId = fixip.subnetId();
1068 gwIp = subnetService.getSubnet(subnetId).gatewayIp();
1069 FixedIp fixedGwIp = FixedIp.fixedIp(fixip.subnetId(), gwIp);
1070 VirtualPort gwPort = virtualPortService.getPort(fixedGwIp);
1071 if (gwPort == null) {
1072 gwPort = VtnData.getPort(vPortStore, fixedGwIp);
1073 }
1074 gwMac = gwPort.macAddress();
1075 }
1076 list.add(gwIp);
1077 list.add(gwMac);
1078 return list;
1079 }
1080
lishuai858efd32015-12-04 14:30:36 +08001081 private void applyHostMonitoredL3Rules(Host host,
1082 Objective.Operation operation) {
1083 String ifaceId = host.annotations().value(IFACEID);
1084 DeviceId deviceId = host.location().deviceId();
1085 VirtualPortId portId = VirtualPortId.portId(ifaceId);
1086 VirtualPort port = virtualPortService.getPort(portId);
1087 if (port == null) {
1088 port = VtnData.getPort(vPortStore, portId);
1089 }
1090 TenantId tenantId = port.tenantId();
1091 Port exPort = exPortOfDevice.get(deviceId);
lishuai858efd32015-12-04 14:30:36 +08001092 Iterator<FixedIp> fixips = port.fixedIps().iterator();
1093 SubnetId sid = null;
1094 IpAddress hostIp = null;
1095 if (fixips.hasNext()) {
1096 FixedIp fixip = fixips.next();
1097 sid = fixip.subnetId();
1098 hostIp = fixip.ip();
1099 }
1100 final SubnetId subnetId = sid;
1101 // L3 internal network access to each other
1102 Iterable<RouterInterface> interfaces = routerInterfaceService
1103 .getRouterInterfaces();
lishuai8798bbe2016-05-05 16:02:03 +08001104 Set<RouterInterface> hostInterfaces = Sets.newHashSet(interfaces)
lishuai858efd32015-12-04 14:30:36 +08001105 .stream().filter(r -> r.tenantId().equals(tenantId))
lishuai8798bbe2016-05-05 16:02:03 +08001106 .filter(r -> r.subnetId().equals(subnetId))
lishuai858efd32015-12-04 14:30:36 +08001107 .collect(Collectors.toSet());
lishuai8798bbe2016-05-05 16:02:03 +08001108 hostInterfaces.stream().forEach(routerInf -> {
1109 Set<RouterInterface> interfacesSet = Sets.newHashSet(interfaces)
1110 .stream().filter(r -> r.tenantId().equals(tenantId))
1111 .filter(r -> r.routerId().equals(routerInf.routerId()))
1112 .collect(Collectors.toSet());
1113 long count = interfacesSet.stream()
1114 .filter(r -> !r.subnetId().equals(subnetId)).count();
1115 if (count > 0) {
1116 TenantRouter tenantRouter = TenantRouter
1117 .tenantRouter(routerInf.tenantId(), routerInf.routerId());
1118 SegmentationId l3vni = vtnRscService.getL3vni(tenantRouter);
1119 if (operation == Objective.Operation.ADD) {
1120 if (routerInfFlagOfTenantRouter.get(tenantRouter) != null) {
1121 applyEastWestL3Flows(host, l3vni, operation);
1122 } else {
1123 if (interfacesSet.size() > 1) {
1124 programInterfacesSet(interfacesSet, operation);
1125 }
1126 }
1127 } else if (operation == Objective.Operation.REMOVE) {
1128 if (routerInfFlagOfTenantRouter.get(tenantRouter) != null) {
1129 applyEastWestL3Flows(host, l3vni, operation);
lishuai858efd32015-12-04 14:30:36 +08001130 }
1131 }
lishuai858efd32015-12-04 14:30:36 +08001132 }
lishuai8798bbe2016-05-05 16:02:03 +08001133 });
lishuai858efd32015-12-04 14:30:36 +08001134 // L3 external and internal network access to each other
1135 FloatingIp floatingIp = null;
1136 Iterable<FloatingIp> floatingIps = floatingIpService.getFloatingIps();
1137 Set<FloatingIp> floatingIpSet = Sets.newHashSet(floatingIps).stream()
1138 .filter(f -> f.tenantId().equals(tenantId))
1139 .collect(Collectors.toSet());
1140 for (FloatingIp f : floatingIpSet) {
1141 IpAddress fixedIp = f.fixedIp();
1142 if (fixedIp.equals(hostIp)) {
1143 floatingIp = f;
1144 break;
1145 }
1146 }
1147 if (floatingIp != null) {
lishuai8798bbe2016-05-05 16:02:03 +08001148 TenantRouter tenantRouter = TenantRouter
1149 .tenantRouter(floatingIp.tenantId(), floatingIp.routerId());
1150 SegmentationId l3vni = vtnRscService.getL3vni(tenantRouter);
lishuai858efd32015-12-04 14:30:36 +08001151 VirtualPort fipPort = virtualPortService
1152 .getPort(floatingIp.networkId(), floatingIp.floatingIp());
1153 if (fipPort == null) {
1154 fipPort = VtnData.getPort(vPortStore, floatingIp.networkId(),
1155 floatingIp.floatingIp());
1156 }
1157 applyNorthSouthL3Flows(deviceId, host, port, fipPort, floatingIp,
1158 l3vni, exPort, operation);
1159 }
1160 }
lishuai74f2d532015-12-10 17:03:34 +08001161
1162 public static void setExPortName(String name) {
lishuaib43dbf72016-01-06 11:11:35 +08001163 exPortMap.put(EX_PORT_KEY, name);
lishuai74f2d532015-12-10 17:03:34 +08001164 }
lishuai6c56f5e2015-11-17 16:38:19 +08001165}