blob: 427aba8a9e8e7732ea74c762c733efe63e3f9aad [file] [log] [blame]
lishuai6c56f5e2015-11-17 16:38:19 +08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
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
Ray Milkeyd84f89b2018-08-17 14:54:17 -070018import com.google.common.collect.Lists;
19import com.google.common.collect.Sets;
Bob zhou59a21062016-05-12 19:40:05 +080020import org.onlab.packet.ARP;
21import org.onlab.packet.Ethernet;
22import org.onlab.packet.IPv4;
jiangruic69a7fd2015-11-19 15:40:01 +080023import org.onlab.packet.Ip4Address;
lishuai6c56f5e2015-11-17 16:38:19 +080024import org.onlab.packet.IpAddress;
Bob zhou59a21062016-05-12 19:40:05 +080025import org.onlab.packet.IpPrefix;
lishuai6c56f5e2015-11-17 16:38:19 +080026import org.onlab.packet.MacAddress;
27import org.onlab.util.KryoNamespace;
28import org.onosproject.core.ApplicationId;
29import org.onosproject.core.CoreService;
30import org.onosproject.mastership.MastershipService;
lishuai858efd32015-12-04 14:30:36 +080031import org.onosproject.net.AnnotationKeys;
Bob zhou59a21062016-05-12 19:40:05 +080032import org.onosproject.net.ConnectPoint;
lishuai6c56f5e2015-11-17 16:38:19 +080033import org.onosproject.net.Device;
34import org.onosproject.net.DeviceId;
35import org.onosproject.net.Host;
lishuai858efd32015-12-04 14:30:36 +080036import org.onosproject.net.HostId;
lishuai6c56f5e2015-11-17 16:38:19 +080037import org.onosproject.net.Port;
38import org.onosproject.net.PortNumber;
39import org.onosproject.net.behaviour.BridgeConfig;
40import org.onosproject.net.behaviour.BridgeDescription;
jiangruic69a7fd2015-11-19 15:40:01 +080041import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
lishuai6c56f5e2015-11-17 16:38:19 +080042import org.onosproject.net.config.NetworkConfigService;
43import org.onosproject.net.config.basics.BasicDeviceConfig;
Phaneendra Mandab212bc92016-07-08 16:50:11 +053044import org.onosproject.net.config.basics.BasicHostConfig;
lishuai6c56f5e2015-11-17 16:38:19 +080045import org.onosproject.net.device.DeviceEvent;
46import org.onosproject.net.device.DeviceListener;
47import org.onosproject.net.device.DeviceService;
48import org.onosproject.net.driver.DriverHandler;
49import org.onosproject.net.driver.DriverService;
jiangruic69a7fd2015-11-19 15:40:01 +080050import org.onosproject.net.flow.DefaultTrafficTreatment;
Bob zhou59a21062016-05-12 19:40:05 +080051import org.onosproject.net.flow.FlowEntry;
52import org.onosproject.net.flow.FlowRuleService;
53import org.onosproject.net.flow.TrafficSelector;
54import org.onosproject.net.flow.TrafficTreatment;
jiangruic69a7fd2015-11-19 15:40:01 +080055import org.onosproject.net.flow.TrafficTreatment.Builder;
Bob zhou59a21062016-05-12 19:40:05 +080056import org.onosproject.net.flow.criteria.Criterion;
jiangruic69a7fd2015-11-19 15:40:01 +080057import org.onosproject.net.flow.instructions.ExtensionTreatment;
lishuai6c56f5e2015-11-17 16:38:19 +080058import org.onosproject.net.flowobjective.Objective;
jiangruic69a7fd2015-11-19 15:40:01 +080059import org.onosproject.net.group.DefaultGroupBucket;
60import org.onosproject.net.group.DefaultGroupDescription;
61import org.onosproject.net.group.DefaultGroupKey;
62import org.onosproject.net.group.GroupBucket;
63import org.onosproject.net.group.GroupBuckets;
64import org.onosproject.net.group.GroupDescription;
65import org.onosproject.net.group.GroupKey;
66import org.onosproject.net.group.GroupService;
lishuai6c56f5e2015-11-17 16:38:19 +080067import org.onosproject.net.host.HostEvent;
68import org.onosproject.net.host.HostListener;
69import org.onosproject.net.host.HostService;
Bob zhou59a21062016-05-12 19:40:05 +080070import org.onosproject.net.packet.DefaultOutboundPacket;
71import org.onosproject.net.packet.InboundPacket;
72import org.onosproject.net.packet.OutboundPacket;
73import org.onosproject.net.packet.PacketContext;
74import org.onosproject.net.packet.PacketProcessor;
75import org.onosproject.net.packet.PacketService;
lishuai6c56f5e2015-11-17 16:38:19 +080076import org.onosproject.store.serializers.KryoNamespaces;
lishuaib43dbf72016-01-06 11:11:35 +080077import org.onosproject.store.service.ConsistentMap;
lishuai6c56f5e2015-11-17 16:38:19 +080078import org.onosproject.store.service.EventuallyConsistentMap;
79import org.onosproject.store.service.LogicalClockService;
lishuaib43dbf72016-01-06 11:11:35 +080080import org.onosproject.store.service.Serializer;
lishuai6c56f5e2015-11-17 16:38:19 +080081import org.onosproject.store.service.StorageService;
lishuaib43dbf72016-01-06 11:11:35 +080082import org.onosproject.store.service.Versioned;
Jonathan Hart51539b82015-10-29 09:53:04 -070083import org.onosproject.vtn.manager.VtnService;
lishuai858efd32015-12-04 14:30:36 +080084import org.onosproject.vtn.table.ArpService;
lishuai6c56f5e2015-11-17 16:38:19 +080085import org.onosproject.vtn.table.ClassifierService;
lishuai858efd32015-12-04 14:30:36 +080086import org.onosproject.vtn.table.DnatService;
lishuai6c56f5e2015-11-17 16:38:19 +080087import org.onosproject.vtn.table.L2ForwardService;
lishuai858efd32015-12-04 14:30:36 +080088import org.onosproject.vtn.table.L3ForwardService;
89import org.onosproject.vtn.table.SnatService;
lishuai74f2d532015-12-10 17:03:34 +080090import org.onosproject.vtn.table.impl.ArpServiceImpl;
lishuai6c56f5e2015-11-17 16:38:19 +080091import org.onosproject.vtn.table.impl.ClassifierServiceImpl;
lishuai74f2d532015-12-10 17:03:34 +080092import org.onosproject.vtn.table.impl.DnatServiceImpl;
lishuai6c56f5e2015-11-17 16:38:19 +080093import org.onosproject.vtn.table.impl.L2ForwardServiceImpl;
lishuai74f2d532015-12-10 17:03:34 +080094import org.onosproject.vtn.table.impl.L3ForwardServiceImpl;
95import org.onosproject.vtn.table.impl.SnatServiceImpl;
lishuai6c56f5e2015-11-17 16:38:19 +080096import org.onosproject.vtn.util.DataPathIdGenerator;
Bob zhou59a21062016-05-12 19:40:05 +080097import org.onosproject.vtn.util.IpUtil;
lishuai6c56f5e2015-11-17 16:38:19 +080098import org.onosproject.vtn.util.VtnConfig;
99import org.onosproject.vtn.util.VtnData;
lishuai7dc63d92015-11-27 17:15:25 +0800100import org.onosproject.vtnrsc.AllowedAddressPair;
101import org.onosproject.vtnrsc.BindingHostId;
Bob zhou59a21062016-05-12 19:40:05 +0800102import org.onosproject.vtnrsc.DefaultFloatingIp;
lishuai7dc63d92015-11-27 17:15:25 +0800103import org.onosproject.vtnrsc.DefaultVirtualPort;
104import org.onosproject.vtnrsc.FixedIp;
lishuai858efd32015-12-04 14:30:36 +0800105import org.onosproject.vtnrsc.FloatingIp;
Bob zhou59a21062016-05-12 19:40:05 +0800106import org.onosproject.vtnrsc.FloatingIpId;
lishuaibee5eca2016-05-10 19:17:37 +0800107import org.onosproject.vtnrsc.RouterId;
lishuai858efd32015-12-04 14:30:36 +0800108import org.onosproject.vtnrsc.RouterInterface;
lishuai7dc63d92015-11-27 17:15:25 +0800109import org.onosproject.vtnrsc.SecurityGroup;
lishuai6c56f5e2015-11-17 16:38:19 +0800110import org.onosproject.vtnrsc.SegmentationId;
Wu wenbinacc10ea2016-05-06 16:48:56 +0800111import org.onosproject.vtnrsc.Subnet;
lishuai6c56f5e2015-11-17 16:38:19 +0800112import org.onosproject.vtnrsc.SubnetId;
113import org.onosproject.vtnrsc.TenantId;
114import org.onosproject.vtnrsc.TenantNetwork;
115import org.onosproject.vtnrsc.TenantNetworkId;
lishuai8798bbe2016-05-05 16:02:03 +0800116import org.onosproject.vtnrsc.TenantRouter;
lishuai6c56f5e2015-11-17 16:38:19 +0800117import org.onosproject.vtnrsc.VirtualPort;
118import org.onosproject.vtnrsc.VirtualPortId;
lishuai858efd32015-12-04 14:30:36 +0800119import org.onosproject.vtnrsc.event.VtnRscEvent;
120import org.onosproject.vtnrsc.event.VtnRscEventFeedback;
121import org.onosproject.vtnrsc.event.VtnRscListener;
122import org.onosproject.vtnrsc.floatingip.FloatingIpService;
lishuai858efd32015-12-04 14:30:36 +0800123import org.onosproject.vtnrsc.routerinterface.RouterInterfaceService;
124import org.onosproject.vtnrsc.service.VtnRscService;
125import org.onosproject.vtnrsc.subnet.SubnetService;
lishuai6c56f5e2015-11-17 16:38:19 +0800126import org.onosproject.vtnrsc.tenantnetwork.TenantNetworkService;
127import org.onosproject.vtnrsc.virtualport.VirtualPortService;
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700128import org.osgi.service.component.annotations.Activate;
129import org.osgi.service.component.annotations.Component;
130import org.osgi.service.component.annotations.Deactivate;
131import org.osgi.service.component.annotations.Reference;
132import org.osgi.service.component.annotations.ReferenceCardinality;
lishuai6c56f5e2015-11-17 16:38:19 +0800133import org.slf4j.Logger;
134
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700135import java.nio.ByteBuffer;
136import java.util.ArrayList;
137import java.util.Arrays;
138import java.util.Collection;
139import java.util.HashMap;
140import java.util.HashSet;
141import java.util.Iterator;
142import java.util.List;
143import java.util.Map;
144import java.util.Set;
145import java.util.UUID;
146import java.util.concurrent.ConcurrentHashMap;
147import java.util.stream.Collectors;
148
149import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST;
150import static org.slf4j.LoggerFactory.getLogger;
lishuai6c56f5e2015-11-17 16:38:19 +0800151
152/**
153 * Provides implementation of VTNService.
154 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700155@Component(immediate = true, service = VtnService.class)
Jonathan Hart51539b82015-10-29 09:53:04 -0700156public class VtnManager implements VtnService {
lishuai6c56f5e2015-11-17 16:38:19 +0800157 private final Logger log = getLogger(getClass());
158 private static final String APP_ID = "org.onosproject.app.vtn";
159
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700160 @Reference(cardinality = ReferenceCardinality.MANDATORY)
lishuai6c56f5e2015-11-17 16:38:19 +0800161 protected NetworkConfigService configService;
162
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700163 @Reference(cardinality = ReferenceCardinality.MANDATORY)
lishuai6c56f5e2015-11-17 16:38:19 +0800164 protected DeviceService deviceService;
165
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700166 @Reference(cardinality = ReferenceCardinality.MANDATORY)
lishuai6c56f5e2015-11-17 16:38:19 +0800167 protected HostService hostService;
168
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700169 @Reference(cardinality = ReferenceCardinality.MANDATORY)
lishuai6c56f5e2015-11-17 16:38:19 +0800170 protected CoreService coreService;
171
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700172 @Reference(cardinality = ReferenceCardinality.MANDATORY)
lishuai6c56f5e2015-11-17 16:38:19 +0800173 protected StorageService storageService;
174
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700175 @Reference(cardinality = ReferenceCardinality.MANDATORY)
lishuai6c56f5e2015-11-17 16:38:19 +0800176 protected TenantNetworkService tenantNetworkService;
177
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700178 @Reference(cardinality = ReferenceCardinality.MANDATORY)
lishuai6c56f5e2015-11-17 16:38:19 +0800179 protected VirtualPortService virtualPortService;
180
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700181 @Reference(cardinality = ReferenceCardinality.MANDATORY)
lishuai6c56f5e2015-11-17 16:38:19 +0800182 protected DriverService driverService;
183
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700184 @Reference(cardinality = ReferenceCardinality.MANDATORY)
lishuai6c56f5e2015-11-17 16:38:19 +0800185 protected LogicalClockService clockService;
186
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700187 @Reference(cardinality = ReferenceCardinality.MANDATORY)
lishuai6c56f5e2015-11-17 16:38:19 +0800188 protected MastershipService mastershipService;
189
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700190 @Reference(cardinality = ReferenceCardinality.MANDATORY)
jiangruic69a7fd2015-11-19 15:40:01 +0800191 protected GroupService groupService;
192
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700193 @Reference(cardinality = ReferenceCardinality.MANDATORY)
lishuai858efd32015-12-04 14:30:36 +0800194 protected SubnetService subnetService;
195
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700196 @Reference(cardinality = ReferenceCardinality.MANDATORY)
lishuai858efd32015-12-04 14:30:36 +0800197 protected VtnRscService vtnRscService;
198
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700199 @Reference(cardinality = ReferenceCardinality.MANDATORY)
lishuai858efd32015-12-04 14:30:36 +0800200 protected FloatingIpService floatingIpService;
201
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700202 @Reference(cardinality = ReferenceCardinality.MANDATORY)
lishuai858efd32015-12-04 14:30:36 +0800203 protected RouterInterfaceService routerInterfaceService;
204
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700205 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Bob zhou59a21062016-05-12 19:40:05 +0800206 protected FlowRuleService flowRuleService;
207
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700208 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Phaneendra Mandab212bc92016-07-08 16:50:11 +0530209 protected NetworkConfigService networkConfigService;
210
lishuai6c56f5e2015-11-17 16:38:19 +0800211 private ApplicationId appId;
212 private ClassifierService classifierService;
213 private L2ForwardService l2ForwardService;
lishuai858efd32015-12-04 14:30:36 +0800214 private ArpService arpService;
215 private L3ForwardService l3ForwardService;
216 private SnatService snatService;
217 private DnatService dnatService;
lishuai6c56f5e2015-11-17 16:38:19 +0800218
219 private final HostListener hostListener = new InnerHostListener();
220 private final DeviceListener deviceListener = new InnerDeviceListener();
lishuai858efd32015-12-04 14:30:36 +0800221 private final VtnRscListener l3EventListener = new VtnL3EventListener();
lishuai6c56f5e2015-11-17 16:38:19 +0800222
lishuaib43dbf72016-01-06 11:11:35 +0800223 private static final String EX_PORT_KEY = "exPortKey";
lishuai6c56f5e2015-11-17 16:38:19 +0800224 private static final String IFACEID = "ifaceid";
225 private static final String CONTROLLER_IP_KEY = "ipaddress";
226 public static final String DRIVER_NAME = "onosfw";
lishuai7dc63d92015-11-27 17:15:25 +0800227 private static final String VIRTUALPORT = "vtn-virtual-port";
lishuai6c56f5e2015-11-17 16:38:19 +0800228 private static final String SWITCHES_OF_CONTROLLER = "switchesOfController";
229 private static final String SWITCH_OF_LOCAL_HOST_PORTS = "switchOfLocalHostPorts";
lishuai8798bbe2016-05-05 16:02:03 +0800230 private static final String ROUTERINF_FLAG_OF_TENANTROUTER = "routerInfFlagOfTenantRouter";
lishuai858efd32015-12-04 14:30:36 +0800231 private static final String HOSTS_OF_SUBNET = "hostsOfSubnet";
232 private static final String EX_PORT_OF_DEVICE = "exPortOfDevice";
lishuaib43dbf72016-01-06 11:11:35 +0800233 private static final String EX_PORT_MAP = "exPortMap";
jiangruic69a7fd2015-11-19 15:40:01 +0800234 private static final String DEFAULT_IP = "0.0.0.0";
Bob zhou59a21062016-05-12 19:40:05 +0800235 private static final String FLOATINGSTORE = "vtn-floatingIp";
Wu wenbinacc10ea2016-05-06 16:48:56 +0800236 private static final String USERDATA_IP = "169.254.169.254";
lishuai858efd32015-12-04 14:30:36 +0800237 private static final int SUBNET_NUM = 2;
Bob zhou59a21062016-05-12 19:40:05 +0800238 private static final int SNAT_TABLE = 40;
239 private static final int SNAT_DEFAULT_RULE_PRIORITY = 0;
240 private static final byte[] ZERO_MAC_ADDRESS = MacAddress.ZERO.toBytes();
lishuai6c56f5e2015-11-17 16:38:19 +0800241
lishuai7dc63d92015-11-27 17:15:25 +0800242 private EventuallyConsistentMap<VirtualPortId, VirtualPort> vPortStore;
lishuai6c56f5e2015-11-17 16:38:19 +0800243 private EventuallyConsistentMap<IpAddress, Boolean> switchesOfController;
jiangruic69a7fd2015-11-19 15:40:01 +0800244 private EventuallyConsistentMap<DeviceId, NetworkOfLocalHostPorts> switchOfLocalHostPorts;
lishuai858efd32015-12-04 14:30:36 +0800245 private EventuallyConsistentMap<SubnetId, Map<HostId, Host>> hostsOfSubnet;
lishuai8798bbe2016-05-05 16:02:03 +0800246 private EventuallyConsistentMap<TenantRouter, Boolean> routerInfFlagOfTenantRouter;
lishuai858efd32015-12-04 14:30:36 +0800247 private EventuallyConsistentMap<DeviceId, Port> exPortOfDevice;
Bob zhou59a21062016-05-12 19:40:05 +0800248 private EventuallyConsistentMap<IpAddress, FloatingIp> floatingIpStore;
lishuaib43dbf72016-01-06 11:11:35 +0800249 private static ConsistentMap<String, String> exPortMap;
lishuai6c56f5e2015-11-17 16:38:19 +0800250
Bob zhou59a21062016-05-12 19:40:05 +0800251 private VtnL3PacketProcessor l3PacketProcessor = new VtnL3PacketProcessor();
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700252 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Bob zhou59a21062016-05-12 19:40:05 +0800253 protected PacketService packetService;
254
lishuai6c56f5e2015-11-17 16:38:19 +0800255 @Activate
256 public void activate() {
257 appId = coreService.registerApplication(APP_ID);
258 classifierService = new ClassifierServiceImpl(appId);
259 l2ForwardService = new L2ForwardServiceImpl(appId);
lishuai74f2d532015-12-10 17:03:34 +0800260 arpService = new ArpServiceImpl(appId);
261 l3ForwardService = new L3ForwardServiceImpl(appId);
262 snatService = new SnatServiceImpl(appId);
263 dnatService = new DnatServiceImpl(appId);
lishuai6c56f5e2015-11-17 16:38:19 +0800264
265 deviceService.addListener(deviceListener);
266 hostService.addListener(hostListener);
lishuai74f2d532015-12-10 17:03:34 +0800267 vtnRscService.addListener(l3EventListener);
lishuai6c56f5e2015-11-17 16:38:19 +0800268
269 KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
270 .register(KryoNamespaces.API)
271 .register(NetworkOfLocalHostPorts.class)
272 .register(TenantNetworkId.class)
273 .register(Host.class)
274 .register(TenantNetwork.class)
Bob zhou59a21062016-05-12 19:40:05 +0800275 .register(TenantNetworkId.class)
lishuai6c56f5e2015-11-17 16:38:19 +0800276 .register(TenantId.class)
lishuai7dc63d92015-11-27 17:15:25 +0800277 .register(SubnetId.class)
278 .register(VirtualPortId.class)
279 .register(VirtualPort.State.class)
280 .register(AllowedAddressPair.class)
281 .register(FixedIp.class)
Bob zhou59a21062016-05-12 19:40:05 +0800282 .register(FloatingIp.class)
283 .register(FloatingIpId.class)
284 .register(FloatingIp.Status.class)
285 .register(UUID.class)
286 .register(DefaultFloatingIp.class)
lishuai7dc63d92015-11-27 17:15:25 +0800287 .register(BindingHostId.class)
288 .register(SecurityGroup.class)
289 .register(IpAddress.class)
lishuaibee5eca2016-05-10 19:17:37 +0800290 .register(DefaultVirtualPort.class)
291 .register(RouterId.class)
292 .register(TenantRouter.class);
Bob zhou59a21062016-05-12 19:40:05 +0800293 floatingIpStore = storageService
294 .<IpAddress, FloatingIp>eventuallyConsistentMapBuilder()
295 .withName(FLOATINGSTORE).withSerializer(serializer)
296 .withTimestampProvider((k, v) -> clockService.getTimestamp())
297 .build();
lishuai7dc63d92015-11-27 17:15:25 +0800298
299 vPortStore = storageService
300 .<VirtualPortId, VirtualPort>eventuallyConsistentMapBuilder()
301 .withName(VIRTUALPORT).withSerializer(serializer)
302 .withTimestampProvider((k, v) -> clockService.getTimestamp())
303 .build();
lishuai6c56f5e2015-11-17 16:38:19 +0800304
305 switchesOfController = storageService
306 .<IpAddress, Boolean>eventuallyConsistentMapBuilder()
307 .withName(SWITCHES_OF_CONTROLLER).withSerializer(serializer)
308 .withTimestampProvider((k, v) -> clockService.getTimestamp())
309 .build();
310
311 switchOfLocalHostPorts = storageService
jiangruic69a7fd2015-11-19 15:40:01 +0800312 .<DeviceId, NetworkOfLocalHostPorts>eventuallyConsistentMapBuilder()
313 .withName(SWITCH_OF_LOCAL_HOST_PORTS).withSerializer(serializer)
314 .withTimestampProvider((k, v) -> clockService.getTimestamp())
lishuai6c56f5e2015-11-17 16:38:19 +0800315 .build();
316
lishuai858efd32015-12-04 14:30:36 +0800317 hostsOfSubnet = storageService
318 .<SubnetId, Map<HostId, Host>>eventuallyConsistentMapBuilder()
319 .withName(HOSTS_OF_SUBNET).withSerializer(serializer)
320 .withTimestampProvider((k, v) -> clockService.getTimestamp())
321 .build();
322
lishuai8798bbe2016-05-05 16:02:03 +0800323 routerInfFlagOfTenantRouter = storageService
324 .<TenantRouter, Boolean>eventuallyConsistentMapBuilder()
325 .withName(ROUTERINF_FLAG_OF_TENANTROUTER).withSerializer(serializer)
lishuai858efd32015-12-04 14:30:36 +0800326 .withTimestampProvider((k, v) -> clockService.getTimestamp())
327 .build();
328
329 exPortOfDevice = storageService
330 .<DeviceId, Port>eventuallyConsistentMapBuilder()
331 .withName(EX_PORT_OF_DEVICE).withSerializer(serializer)
332 .withTimestampProvider((k, v) -> clockService.getTimestamp())
333 .build();
334
lishuaib43dbf72016-01-06 11:11:35 +0800335 exPortMap = storageService
336 .<String, String>consistentMapBuilder()
337 .withName(EX_PORT_MAP)
338 .withApplicationId(appId)
339 .withPurgeOnUninstall()
340 .withSerializer(Serializer.using(Arrays.asList(KryoNamespaces.API)))
341 .build();
342
Bob zhou59a21062016-05-12 19:40:05 +0800343 packetService.addProcessor(l3PacketProcessor, PacketProcessor.director(0));
lishuai6c56f5e2015-11-17 16:38:19 +0800344 log.info("Started");
345 }
346
347 @Deactivate
348 public void deactivate() {
349 deviceService.removeListener(deviceListener);
350 hostService.removeListener(hostListener);
lishuai858efd32015-12-04 14:30:36 +0800351 vtnRscService.removeListener(l3EventListener);
lishuai6c56f5e2015-11-17 16:38:19 +0800352 log.info("Stopped");
353 }
354
355 @Override
356 public void onControllerDetected(Device controllerDevice) {
357 if (controllerDevice == null) {
358 log.error("The controller device is null");
359 return;
360 }
361 String localIpAddress = controllerDevice.annotations()
362 .value(CONTROLLER_IP_KEY);
363 IpAddress localIp = IpAddress.valueOf(localIpAddress);
364 DeviceId controllerDeviceId = controllerDevice.id();
365 DriverHandler handler = driverService.createHandler(controllerDeviceId);
366 if (mastershipService.isLocalMaster(controllerDeviceId)) {
367 // Get DataPathIdGenerator
368 String ipaddress = controllerDevice.annotations().value("ipaddress");
369 DataPathIdGenerator dpidGenerator = DataPathIdGenerator.builder()
370 .addIpAddress(ipaddress).build();
371 DeviceId deviceId = dpidGenerator.getDeviceId();
372 String dpid = dpidGenerator.getDpId();
373 // Inject pipeline driver name
374 BasicDeviceConfig config = configService.addConfig(deviceId,
375 BasicDeviceConfig.class);
376 config.driver(DRIVER_NAME);
377 configService.applyConfig(deviceId, BasicDeviceConfig.class, config.node());
378 // Add Bridge
lishuaib43dbf72016-01-06 11:11:35 +0800379 Versioned<String> exPortVersioned = exPortMap.get(EX_PORT_KEY);
380 if (exPortVersioned != null) {
381 VtnConfig.applyBridgeConfig(handler, dpid, exPortVersioned.value());
382 log.info("A new ovs is created in node {}", localIp.toString());
383 }
lishuai6c56f5e2015-11-17 16:38:19 +0800384 switchesOfController.put(localIp, true);
385 }
386 // Create tunnel in br-int on all controllers
387 programTunnelConfig(controllerDeviceId, localIp, handler);
388 }
389
390 @Override
391 public void onControllerVanished(Device controllerDevice) {
392 if (controllerDevice == null) {
393 log.error("The device is null");
394 return;
395 }
396 String dstIp = controllerDevice.annotations().value(CONTROLLER_IP_KEY);
397 IpAddress dstIpAddress = IpAddress.valueOf(dstIp);
398 DeviceId controllerDeviceId = controllerDevice.id();
399 if (mastershipService.isLocalMaster(controllerDeviceId)) {
400 switchesOfController.remove(dstIpAddress);
401 }
lishuai6c56f5e2015-11-17 16:38:19 +0800402 }
403
404 @Override
405 public void onOvsDetected(Device device) {
lishuaibee5eca2016-05-10 19:17:37 +0800406 if (device == null) {
407 log.error("The device is null");
408 return;
409 }
410 if (!mastershipService.isLocalMaster(device.id())) {
411 return;
412 }
lishuai6c56f5e2015-11-17 16:38:19 +0800413 // Create tunnel out flow rules
414 applyTunnelOut(device, Objective.Operation.ADD);
lishuaibee5eca2016-05-10 19:17:37 +0800415 // apply L3 arp flows
416 Iterable<RouterInterface> interfaces = routerInterfaceService
417 .getRouterInterfaces();
418 interfaces.forEach(routerInf -> {
419 VirtualPort gwPort = virtualPortService.getPort(routerInf.portId());
420 if (gwPort == null) {
421 gwPort = VtnData.getPort(vPortStore, routerInf.portId());
422 }
423 applyL3ArpFlows(device.id(), gwPort, Objective.Operation.ADD);
424 });
lishuai6c56f5e2015-11-17 16:38:19 +0800425 }
426
427 @Override
428 public void onOvsVanished(Device device) {
lishuaibee5eca2016-05-10 19:17:37 +0800429 if (device == null) {
430 log.error("The device is null");
431 return;
432 }
433 if (!mastershipService.isLocalMaster(device.id())) {
434 return;
435 }
lishuai6c56f5e2015-11-17 16:38:19 +0800436 // Remove Tunnel out flow rules
437 applyTunnelOut(device, Objective.Operation.REMOVE);
lishuaibee5eca2016-05-10 19:17:37 +0800438 // apply L3 arp flows
439 Iterable<RouterInterface> interfaces = routerInterfaceService
440 .getRouterInterfaces();
441 interfaces.forEach(routerInf -> {
442 VirtualPort gwPort = virtualPortService.getPort(routerInf.portId());
443 if (gwPort == null) {
444 gwPort = VtnData.getPort(vPortStore, routerInf.portId());
445 }
446 applyL3ArpFlows(device.id(), gwPort, Objective.Operation.REMOVE);
447 });
lishuai6c56f5e2015-11-17 16:38:19 +0800448 }
449
450 @Override
451 public void onHostDetected(Host host) {
lishuai858efd32015-12-04 14:30:36 +0800452 DeviceId deviceId = host.location().deviceId();
453 if (!mastershipService.isLocalMaster(deviceId)) {
454 return;
455 }
456 String ifaceId = host.annotations().value(IFACEID);
457 if (ifaceId == null) {
458 log.error("The ifaceId of Host is null");
459 return;
460 }
lishuaib43dbf72016-01-06 11:11:35 +0800461 programSffAndClassifierHost(host, Objective.Operation.ADD);
lishuai6c56f5e2015-11-17 16:38:19 +0800462 // apply L2 openflow rules
463 applyHostMonitoredL2Rules(host, Objective.Operation.ADD);
lishuai858efd32015-12-04 14:30:36 +0800464 // apply L3 openflow rules
465 applyHostMonitoredL3Rules(host, Objective.Operation.ADD);
lishuai6c56f5e2015-11-17 16:38:19 +0800466 }
467
468 @Override
469 public void onHostVanished(Host host) {
lishuai858efd32015-12-04 14:30:36 +0800470 DeviceId deviceId = host.location().deviceId();
471 if (!mastershipService.isLocalMaster(deviceId)) {
472 return;
473 }
474 String ifaceId = host.annotations().value(IFACEID);
475 if (ifaceId == null) {
476 log.error("The ifaceId of Host is null");
477 return;
478 }
lishuaib43dbf72016-01-06 11:11:35 +0800479 programSffAndClassifierHost(host, Objective.Operation.REMOVE);
lishuai6c56f5e2015-11-17 16:38:19 +0800480 // apply L2 openflow rules
481 applyHostMonitoredL2Rules(host, Objective.Operation.REMOVE);
lishuai858efd32015-12-04 14:30:36 +0800482 // apply L3 openflow rules
483 applyHostMonitoredL3Rules(host, Objective.Operation.REMOVE);
lishuai590d93a2015-12-11 13:05:14 +0800484 VirtualPortId virtualPortId = VirtualPortId.portId(ifaceId);
485 vPortStore.remove(virtualPortId);
lishuai6c56f5e2015-11-17 16:38:19 +0800486 }
487
488 private void programTunnelConfig(DeviceId localDeviceId, IpAddress localIp,
489 DriverHandler localHandler) {
jiangruic69a7fd2015-11-19 15:40:01 +0800490 if (mastershipService.isLocalMaster(localDeviceId)) {
Hyunsun Moondd14e8e2016-06-09 16:17:32 -0700491 VtnConfig.applyTunnelConfig(localHandler, localIp);
jiangruic69a7fd2015-11-19 15:40:01 +0800492 log.info("Add tunnel on {}", localIp);
493 }
lishuai6c56f5e2015-11-17 16:38:19 +0800494 }
495
496 private void applyTunnelOut(Device device, Objective.Operation type) {
lishuai6c56f5e2015-11-17 16:38:19 +0800497 String controllerIp = VtnData.getControllerIpOfSwitch(device);
498 if (controllerIp == null) {
499 log.error("Can't find controller of device: {}",
500 device.id().toString());
501 return;
502 }
503 IpAddress ipAddress = IpAddress.valueOf(controllerIp);
504 if (!switchesOfController.containsKey(ipAddress)) {
505 log.error("Can't find controller of device: {}",
506 device.id().toString());
507 return;
508 }
509 if (type == Objective.Operation.ADD) {
lishuaia3e32342015-12-07 10:59:17 +0800510 // Save external port
511 Port export = getExPort(device.id());
lishuaid6f0c9e2015-12-16 11:40:01 +0800512 if (export != null) {
Bob zhou59a21062016-05-12 19:40:05 +0800513 classifierService.programExportPortArpClassifierRules(export,
514 device.id(),
515 type);
lishuaid6f0c9e2015-12-16 11:40:01 +0800516 exPortOfDevice.put(device.id(), export);
517 }
lishuai6c56f5e2015-11-17 16:38:19 +0800518 switchOfLocalHostPorts.put(device.id(), new NetworkOfLocalHostPorts());
519 } else if (type == Objective.Operation.REMOVE) {
lishuaia3e32342015-12-07 10:59:17 +0800520 exPortOfDevice.remove(device.id());
lishuai6c56f5e2015-11-17 16:38:19 +0800521 switchOfLocalHostPorts.remove(device.id());
522 }
523 Iterable<Device> devices = deviceService.getAvailableDevices();
524 DeviceId localControllerId = VtnData.getControllerId(device, devices);
525 DriverHandler handler = driverService.createHandler(localControllerId);
526 Set<PortNumber> ports = VtnConfig.getPortNumbers(handler);
527 Iterable<Host> allHosts = hostService.getHosts();
jiangruic69a7fd2015-11-19 15:40:01 +0800528 String tunnelName = "vxlan-" + DEFAULT_IP;
lishuai6c56f5e2015-11-17 16:38:19 +0800529 if (allHosts != null) {
Sho SHIMIZUa09e1bb2016-08-01 14:25:25 -0700530 Sets.newHashSet(allHosts).forEach(host -> {
lishuai6c56f5e2015-11-17 16:38:19 +0800531 MacAddress hostMac = host.mac();
532 String ifaceId = host.annotations().value(IFACEID);
533 if (ifaceId == null) {
534 log.error("The ifaceId of Host is null");
535 return;
536 }
537 VirtualPortId virtualPortId = VirtualPortId.portId(ifaceId);
538 VirtualPort virtualPort = virtualPortService
539 .getPort(virtualPortId);
540 TenantNetwork network = tenantNetworkService
541 .getNetwork(virtualPort.networkId());
542 SegmentationId segmentationId = network.segmentationId();
543 DeviceId remoteDeviceId = host.location().deviceId();
544 Device remoteDevice = deviceService.getDevice(remoteDeviceId);
545 String remoteControllerIp = VtnData
546 .getControllerIpOfSwitch(remoteDevice);
547 if (remoteControllerIp == null) {
548 log.error("Can't find remote controller of device: {}",
Sho SHIMIZUa09e1bb2016-08-01 14:25:25 -0700549 remoteDeviceId.toString());
lishuai6c56f5e2015-11-17 16:38:19 +0800550 return;
551 }
552 IpAddress remoteIpAddress = IpAddress
553 .valueOf(remoteControllerIp);
lishuai6c56f5e2015-11-17 16:38:19 +0800554 ports.stream()
555 .filter(p -> p.name().equalsIgnoreCase(tunnelName))
556 .forEach(p -> {
Sho SHIMIZUa09e1bb2016-08-01 14:25:25 -0700557 l2ForwardService
558 .programTunnelOut(device.id(), segmentationId, p,
559 hostMac, type, remoteIpAddress);
560 });
lishuai6c56f5e2015-11-17 16:38:19 +0800561 });
562 }
563 }
564
lishuaib43dbf72016-01-06 11:11:35 +0800565 private void programSffAndClassifierHost(Host host, Objective.Operation type) {
566 DeviceId deviceId = host.location().deviceId();
567 String ifaceId = host.annotations().value(IFACEID);
568 VirtualPortId virtualPortId = VirtualPortId.portId(ifaceId);
569 VirtualPort virtualPort = virtualPortService.getPort(virtualPortId);
570 if (virtualPort == null) {
571 virtualPort = VtnData.getPort(vPortStore, virtualPortId);
572 }
573 TenantId tenantId = virtualPort.tenantId();
574 if (Objective.Operation.ADD == type) {
575 vtnRscService.addDeviceIdOfOvsMap(virtualPortId, tenantId, deviceId);
576 } else if (Objective.Operation.REMOVE == type) {
577 vtnRscService.removeDeviceIdOfOvsMap(host, tenantId, deviceId);
578 }
579 }
580
lishuai6c56f5e2015-11-17 16:38:19 +0800581 private void applyHostMonitoredL2Rules(Host host, Objective.Operation type) {
582 DeviceId deviceId = host.location().deviceId();
583 if (!mastershipService.isLocalMaster(deviceId)) {
584 return;
585 }
586 String ifaceId = host.annotations().value(IFACEID);
587 if (ifaceId == null) {
588 log.error("The ifaceId of Host is null");
589 return;
590 }
591 VirtualPortId virtualPortId = VirtualPortId.portId(ifaceId);
592 VirtualPort virtualPort = virtualPortService.getPort(virtualPortId);
593 if (virtualPort == null) {
lishuai858efd32015-12-04 14:30:36 +0800594 virtualPort = VtnData.getPort(vPortStore, virtualPortId);
lishuai6c56f5e2015-11-17 16:38:19 +0800595 }
lishuai74f2d532015-12-10 17:03:34 +0800596 Iterator<FixedIp> fixip = virtualPort.fixedIps().iterator();
597 SubnetId subnetId = null;
598 if (fixip.hasNext()) {
599 subnetId = fixip.next().subnetId();
600 }
601 if (subnetId != null) {
602 Map<HostId, Host> hosts = new ConcurrentHashMap();
603 if (hostsOfSubnet.get(subnetId) != null) {
604 hosts = hostsOfSubnet.get(subnetId);
605 }
606 if (type == Objective.Operation.ADD) {
607 hosts.put(host.id(), host);
608 hostsOfSubnet.put(subnetId, hosts);
609 } else if (type == Objective.Operation.REMOVE) {
610 hosts.remove(host.id());
611 if (hosts.size() != 0) {
612 hostsOfSubnet.put(subnetId, hosts);
613 } else {
614 hostsOfSubnet.remove(subnetId);
615 }
616 }
617 }
lishuai6c56f5e2015-11-17 16:38:19 +0800618
619 Iterable<Device> devices = deviceService.getAvailableDevices();
620 PortNumber inPort = host.location().port();
621 MacAddress mac = host.mac();
622 Device device = deviceService.getDevice(deviceId);
623 String controllerIp = VtnData.getControllerIpOfSwitch(device);
624 IpAddress ipAddress = IpAddress.valueOf(controllerIp);
625 TenantNetwork network = tenantNetworkService.getNetwork(virtualPort.networkId());
626 if (network == null) {
627 log.error("Can't find network of the host");
628 return;
629 }
630 SegmentationId segmentationId = network.segmentationId();
631 // Get all the tunnel PortNumber in the current node
632 Iterable<Port> ports = deviceService.getPorts(deviceId);
633 Collection<PortNumber> localTunnelPorts = VtnData.getLocalTunnelPorts(ports);
634 // Get all the local vm's PortNumber in the current node
635 Map<TenantNetworkId, Set<PortNumber>> localHostPorts = switchOfLocalHostPorts
jiangruic69a7fd2015-11-19 15:40:01 +0800636 .get(deviceId).getNetworkOfLocalHostPorts();
lishuai6c56f5e2015-11-17 16:38:19 +0800637 Set<PortNumber> networkOflocalHostPorts = localHostPorts.get(network.id());
jiangruic69a7fd2015-11-19 15:40:01 +0800638 for (PortNumber p : localTunnelPorts) {
639 programGroupTable(deviceId, appId, p, devices, type);
640 }
Wu wenbinacc10ea2016-05-06 16:48:56 +0800641 Subnet subnet = subnetService.getSubnet(subnetId);
642 String deviceOwner = virtualPort.deviceOwner();
643 if (deviceOwner != null) {
Jon Halla3fcf672017-03-28 16:53:22 -0700644 if ("network:dhcp".equalsIgnoreCase(deviceOwner)) {
Wu wenbinacc10ea2016-05-06 16:48:56 +0800645 Sets.newHashSet(devices).stream()
646 .filter(d -> d.type() == Device.Type.SWITCH)
647 .forEach(d -> {
648 if (subnet != null) {
649 IpAddress dstIp = IpAddress
650 .valueOf(USERDATA_IP);
651 classifierService
652 .programUserdataClassifierRules(d.id(),
653 subnet.cidr(),
654 dstIp,
655 mac,
656 segmentationId,
657 type);
658 }
659 });
660 }
661 }
lishuai6c56f5e2015-11-17 16:38:19 +0800662 if (type == Objective.Operation.ADD) {
lishuai7dc63d92015-11-27 17:15:25 +0800663 vPortStore.put(virtualPortId, virtualPort);
lishuai6c56f5e2015-11-17 16:38:19 +0800664 if (networkOflocalHostPorts == null) {
665 networkOflocalHostPorts = new HashSet<PortNumber>();
666 localHostPorts.putIfAbsent(network.id(), networkOflocalHostPorts);
667 }
668 networkOflocalHostPorts.add(inPort);
jiangruic69a7fd2015-11-19 15:40:01 +0800669 l2ForwardService.programLocalBcastRules(deviceId, segmentationId,
670 inPort, networkOflocalHostPorts,
671 localTunnelPorts,
672 type);
lishuai6c56f5e2015-11-17 16:38:19 +0800673 classifierService.programTunnelIn(deviceId, segmentationId,
674 localTunnelPorts,
675 type);
676 } else if (type == Objective.Operation.REMOVE) {
jiangruic69a7fd2015-11-19 15:40:01 +0800677 if (networkOflocalHostPorts != null) {
678 l2ForwardService.programLocalBcastRules(deviceId, segmentationId,
679 inPort, networkOflocalHostPorts,
680 localTunnelPorts,
681 type);
682 networkOflocalHostPorts.remove(inPort);
683 if (networkOflocalHostPorts.isEmpty()) {
684 classifierService.programTunnelIn(deviceId, segmentationId,
685 localTunnelPorts,
686 type);
687 switchOfLocalHostPorts.get(deviceId).getNetworkOfLocalHostPorts()
688 .remove(virtualPort.networkId());
689 }
lishuai6c56f5e2015-11-17 16:38:19 +0800690 }
691 }
692
jiangruic69a7fd2015-11-19 15:40:01 +0800693 l2ForwardService.programLocalOut(deviceId, segmentationId, inPort, mac,
694 type);
695
lishuai6c56f5e2015-11-17 16:38:19 +0800696 l2ForwardService.programTunnelBcastRules(deviceId, segmentationId,
697 networkOflocalHostPorts,
698 localTunnelPorts,
699 type);
700
701 programTunnelOuts(devices, ipAddress, segmentationId, mac,
702 type);
703
704 classifierService.programLocalIn(deviceId, segmentationId, inPort, mac,
705 appId, type);
706 }
707
708 private void programTunnelOuts(Iterable<Device> devices,
709 IpAddress ipAddress,
710 SegmentationId segmentationId,
711 MacAddress dstMac,
712 Objective.Operation type) {
jiangruic69a7fd2015-11-19 15:40:01 +0800713 String tunnelName = "vxlan-" + DEFAULT_IP;
lishuai6c56f5e2015-11-17 16:38:19 +0800714 Sets.newHashSet(devices).stream()
jiangruic69a7fd2015-11-19 15:40:01 +0800715 .filter(d -> d.type() == Device.Type.CONTROLLER)
716 .filter(d -> !("ovsdb:" + ipAddress).equals(d.id().toString()))
717 .forEach(d -> {
lishuai6c56f5e2015-11-17 16:38:19 +0800718 DriverHandler handler = driverService.createHandler(d.id());
Hyunsun Moon1251e192016-06-07 16:57:05 -0700719 BridgeConfig bridgeConfig = handler.behaviour(BridgeConfig.class);
720 Collection<BridgeDescription> bridgeDescriptions = bridgeConfig.getBridges();
721 for (BridgeDescription sw : bridgeDescriptions) {
722 if (sw.name().equals(VtnConfig.DEFAULT_BRIDGE_NAME) &&
723 sw.deviceId().isPresent()) {
724 List<Port> ports = deviceService.getPorts(sw.deviceId().get());
725 ports.stream().filter(p -> p.annotations().value(AnnotationKeys.PORT_NAME)
726 .equalsIgnoreCase(tunnelName))
727 .forEach(p -> l2ForwardService.programTunnelOut(
728 sw.deviceId().get(), segmentationId, p.number(),
729 dstMac, type, ipAddress));
lishuai70304d12015-12-14 17:15:26 +0800730 break;
731 }
lishuai6c56f5e2015-11-17 16:38:19 +0800732 }
733 });
734 }
735
736 private class InnerDeviceListener implements DeviceListener {
737
738 @Override
739 public void event(DeviceEvent event) {
740 Device device = event.subject();
741 if (Device.Type.CONTROLLER == device.type()) {
742 if (DeviceEvent.Type.DEVICE_ADDED == event.type()) {
743 onControllerDetected(device);
744 }
745 if (DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED == event.type()) {
746 if (deviceService.isAvailable(device.id())) {
747 onControllerDetected(device);
748 } else {
749 onControllerVanished(device);
750 }
751 }
752 } else if (Device.Type.SWITCH == device.type()) {
753 if (DeviceEvent.Type.DEVICE_ADDED == event.type()) {
754 onOvsDetected(device);
755 }
756 if (DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED == event.type()) {
757 if (deviceService.isAvailable(device.id())) {
758 onOvsDetected(device);
759 } else {
760 onOvsVanished(device);
761 }
762 }
763 } else {
764 log.info("Do nothing for this device type");
765 }
766 }
767 }
768
769 private class InnerHostListener implements HostListener {
770
771 @Override
772 public void event(HostEvent event) {
773 Host host = event.subject();
774 if (HostEvent.Type.HOST_ADDED == event.type()) {
775 onHostDetected(host);
776 } else if (HostEvent.Type.HOST_REMOVED == event.type()) {
777 onHostVanished(host);
778 } else if (HostEvent.Type.HOST_UPDATED == event.type()) {
779 onHostVanished(host);
780 onHostDetected(host);
781 }
782 }
783
784 }
785
786 // Local Host Ports of Network.
787 private class NetworkOfLocalHostPorts {
788 private final Map<TenantNetworkId, Set<PortNumber>> networkOfLocalHostPorts =
789 new HashMap<TenantNetworkId, Set<PortNumber>>();
790
791 public Map<TenantNetworkId, Set<PortNumber>> getNetworkOfLocalHostPorts() {
792 return networkOfLocalHostPorts;
793 }
794 }
795
jiangruic69a7fd2015-11-19 15:40:01 +0800796 private void programGroupTable(DeviceId deviceId, ApplicationId appid,
797 PortNumber portNumber, Iterable<Device> devices, Objective.Operation type) {
798 if (type.equals(Objective.Operation.REMOVE)) {
799 return;
800 }
801
802 List<GroupBucket> buckets = Lists.newArrayList();
803 Sets.newHashSet(devices)
804 .stream()
805 .filter(d -> d.type() == Device.Type.CONTROLLER)
806 .filter(d -> !deviceId.equals(d.id()))
807 .forEach(d -> {
808 String ipAddress = d.annotations()
809 .value(CONTROLLER_IP_KEY);
810 Ip4Address dst = Ip4Address.valueOf(ipAddress);
811 Builder builder = DefaultTrafficTreatment.builder();
812
813 DriverHandler handler = driverService.createHandler(deviceId);
814 ExtensionTreatmentResolver resolver = handler.behaviour(ExtensionTreatmentResolver.class);
815 ExtensionTreatment treatment = resolver.getExtensionInstruction(NICIRA_SET_TUNNEL_DST.type());
816 try {
817 treatment.setPropertyValue("tunnelDst", dst);
818 } catch (Exception e) {
819 log.error("Failed to get extension instruction to set tunnel dst {}", deviceId);
820 }
821
822 builder.extension(treatment, deviceId);
823 builder.setOutput(portNumber);
824 GroupBucket bucket = DefaultGroupBucket
825 .createAllGroupBucket(builder.build());
826 buckets.add(bucket);
827 });
828 final GroupKey key = new DefaultGroupKey(APP_ID.getBytes());
829 GroupDescription groupDescription = new DefaultGroupDescription(deviceId,
830 GroupDescription.Type.ALL,
831 new GroupBuckets(buckets),
832 key,
833 L2ForwardServiceImpl.GROUP_ID,
834 appid);
835 groupService.addGroup(groupDescription);
836 }
lishuai858efd32015-12-04 14:30:36 +0800837
838 private class VtnL3EventListener implements VtnRscListener {
839 @Override
840 public void event(VtnRscEvent event) {
841 VtnRscEventFeedback l3Feedback = event.subject();
842 if (VtnRscEvent.Type.ROUTER_INTERFACE_PUT == event.type()) {
843 onRouterInterfaceDetected(l3Feedback);
Phaneendra Mandab212bc92016-07-08 16:50:11 +0530844 } else if (VtnRscEvent.Type.ROUTER_INTERFACE_DELETE == event.type()) {
lishuai858efd32015-12-04 14:30:36 +0800845 onRouterInterfaceVanished(l3Feedback);
lishuai762df812016-01-08 11:51:15 +0800846 } else if (VtnRscEvent.Type.FLOATINGIP_BIND == event.type()) {
lishuai858efd32015-12-04 14:30:36 +0800847 onFloatingIpDetected(l3Feedback);
lishuai762df812016-01-08 11:51:15 +0800848 } else if (VtnRscEvent.Type.FLOATINGIP_UNBIND == event.type()) {
lishuai858efd32015-12-04 14:30:36 +0800849 onFloatingIpVanished(l3Feedback);
Phaneendra Mandab212bc92016-07-08 16:50:11 +0530850 } else if (VtnRscEvent.Type.VIRTUAL_PORT_PUT == event.type()) {
851 onVirtualPortCreated(l3Feedback);
852 } else if (VtnRscEvent.Type.VIRTUAL_PORT_DELETE == event.type()) {
853 onVirtualPortDeleted(l3Feedback);
lishuai858efd32015-12-04 14:30:36 +0800854 }
855 }
856
857 }
858
859 @Override
860 public void onRouterInterfaceDetected(VtnRscEventFeedback l3Feedback) {
861 Objective.Operation operation = Objective.Operation.ADD;
862 RouterInterface routerInf = l3Feedback.routerInterface();
lishuai762df812016-01-08 11:51:15 +0800863 VirtualPort gwPort = virtualPortService.getPort(routerInf.portId());
864 vPortStore.put(gwPort.portId(), gwPort);
lishuai858efd32015-12-04 14:30:36 +0800865 Iterable<RouterInterface> interfaces = routerInterfaceService
866 .getRouterInterfaces();
lishuai8798bbe2016-05-05 16:02:03 +0800867 Set<RouterInterface> interfacesSet = Sets.newHashSet(interfaces).stream()
868 .filter(r -> r.tenantId().equals(routerInf.tenantId()))
869 .filter(r -> r.routerId().equals(routerInf.routerId()))
lishuai858efd32015-12-04 14:30:36 +0800870 .collect(Collectors.toSet());
lishuai8798bbe2016-05-05 16:02:03 +0800871 TenantRouter tenantRouter = TenantRouter
872 .tenantRouter(routerInf.tenantId(), routerInf.routerId());
873 if (routerInfFlagOfTenantRouter.get(tenantRouter) != null) {
lishuai858efd32015-12-04 14:30:36 +0800874 programRouterInterface(routerInf, operation);
875 } else {
876 if (interfacesSet.size() >= SUBNET_NUM) {
877 programInterfacesSet(interfacesSet, operation);
878 }
879 }
lishuaibee5eca2016-05-10 19:17:37 +0800880 // apply L3 arp flows
881 applyL3ArpFlows(null, gwPort, operation);
lishuai858efd32015-12-04 14:30:36 +0800882 }
883
884 @Override
885 public void onRouterInterfaceVanished(VtnRscEventFeedback l3Feedback) {
886 Objective.Operation operation = Objective.Operation.REMOVE;
887 RouterInterface routerInf = l3Feedback.routerInterface();
888 Iterable<RouterInterface> interfaces = routerInterfaceService
889 .getRouterInterfaces();
890 Set<RouterInterface> interfacesSet = Sets.newHashSet(interfaces)
891 .stream().filter(r -> r.tenantId().equals(routerInf.tenantId()))
892 .collect(Collectors.toSet());
lishuai8798bbe2016-05-05 16:02:03 +0800893 TenantRouter tenantRouter = TenantRouter
894 .tenantRouter(routerInf.tenantId(), routerInf.routerId());
895 if (routerInfFlagOfTenantRouter.get(tenantRouter) != null) {
lishuai858efd32015-12-04 14:30:36 +0800896 programRouterInterface(routerInf, operation);
897 if (interfacesSet.size() == 1) {
lishuai8798bbe2016-05-05 16:02:03 +0800898 routerInfFlagOfTenantRouter.remove(tenantRouter);
Sho SHIMIZUa09e1bb2016-08-01 14:25:25 -0700899 interfacesSet.forEach(r -> {
lishuai858efd32015-12-04 14:30:36 +0800900 programRouterInterface(r, operation);
901 });
902 }
903 }
lishuai762df812016-01-08 11:51:15 +0800904 VirtualPort gwPort = virtualPortService.getPort(routerInf.portId());
905 if (gwPort == null) {
906 gwPort = VtnData.getPort(vPortStore, routerInf.portId());
907 }
908 vPortStore.remove(gwPort.portId());
lishuaibee5eca2016-05-10 19:17:37 +0800909 // apply L3 arp flows
910 applyL3ArpFlows(null, gwPort, operation);
lishuai858efd32015-12-04 14:30:36 +0800911 }
912
913 @Override
914 public void onFloatingIpDetected(VtnRscEventFeedback l3Feedback) {
Bob zhou59a21062016-05-12 19:40:05 +0800915 floatingIpStore.put(l3Feedback.floatingIp().floatingIp(),
916 l3Feedback.floatingIp());
lishuai762df812016-01-08 11:51:15 +0800917 programFloatingIpEvent(l3Feedback, VtnRscEvent.Type.FLOATINGIP_BIND);
lishuai858efd32015-12-04 14:30:36 +0800918 }
919
920 @Override
921 public void onFloatingIpVanished(VtnRscEventFeedback l3Feedback) {
Bob zhou59a21062016-05-12 19:40:05 +0800922 floatingIpStore.remove(l3Feedback.floatingIp().floatingIp());
lishuai762df812016-01-08 11:51:15 +0800923 programFloatingIpEvent(l3Feedback, VtnRscEvent.Type.FLOATINGIP_UNBIND);
lishuai858efd32015-12-04 14:30:36 +0800924 }
925
Phaneendra Mandab212bc92016-07-08 16:50:11 +0530926 public void onVirtualPortCreated(VtnRscEventFeedback l3Feedback) {
927 VirtualPort vPort = l3Feedback.virtualPort();
928 BasicHostConfig basicHostConfig = networkConfigService.addConfig(HostId.hostId(vPort.macAddress()),
929 BasicHostConfig.class);
930 Set<IpAddress> ips = new HashSet<>();
931 for (FixedIp fixedIp : vPort.fixedIps()) {
932 ips.add(fixedIp.ip());
933 }
934 basicHostConfig.setIps(ips).apply();
935 }
936
937 public void onVirtualPortDeleted(VtnRscEventFeedback l3Feedback) {
938 VirtualPort vPort = l3Feedback.virtualPort();
939 HostId hostId = HostId.hostId(vPort.macAddress());
940 BasicHostConfig basicHostConfig = networkConfigService.addConfig(hostId,
941 BasicHostConfig.class);
Phaneendra Mandac11e57a2017-05-03 19:03:21 +0530942 Set<IpAddress> oldIps = hostService.getHost(hostId).ipAddresses();
943 // Copy to a new set as oldIps is unmodifiable set.
944 Set<IpAddress> newIps = new HashSet<>();
945 newIps.addAll(oldIps);
Phaneendra Mandab212bc92016-07-08 16:50:11 +0530946 for (FixedIp fixedIp : vPort.fixedIps()) {
Phaneendra Mandac11e57a2017-05-03 19:03:21 +0530947 newIps.remove(fixedIp.ip());
Phaneendra Mandab212bc92016-07-08 16:50:11 +0530948 }
Phaneendra Mandac11e57a2017-05-03 19:03:21 +0530949 basicHostConfig.setIps(newIps).apply();
Phaneendra Mandab212bc92016-07-08 16:50:11 +0530950 }
951
lishuai858efd32015-12-04 14:30:36 +0800952 private void programInterfacesSet(Set<RouterInterface> interfacesSet,
953 Objective.Operation operation) {
954 int subnetVmNum = 0;
955 for (RouterInterface r : interfacesSet) {
956 // Get all the host of the subnet
957 Map<HostId, Host> hosts = hostsOfSubnet.get(r.subnetId());
lishuaid6f0c9e2015-12-16 11:40:01 +0800958 if (hosts != null && hosts.size() > 0) {
lishuai858efd32015-12-04 14:30:36 +0800959 subnetVmNum++;
960 if (subnetVmNum >= SUBNET_NUM) {
lishuai8798bbe2016-05-05 16:02:03 +0800961 TenantRouter tenantRouter = TenantRouter
962 .tenantRouter(r.tenantId(), r.routerId());
963 routerInfFlagOfTenantRouter.put(tenantRouter, true);
Sho SHIMIZUa09e1bb2016-08-01 14:25:25 -0700964 interfacesSet.forEach(f -> {
lishuai858efd32015-12-04 14:30:36 +0800965 programRouterInterface(f, operation);
966 });
967 break;
968 }
969 }
970 }
971 }
972
973 private void programRouterInterface(RouterInterface routerInf,
974 Objective.Operation operation) {
lishuai8798bbe2016-05-05 16:02:03 +0800975 TenantRouter tenantRouter = TenantRouter
976 .tenantRouter(routerInf.tenantId(), routerInf.routerId());
977 SegmentationId l3vni = vtnRscService.getL3vni(tenantRouter);
lishuai858efd32015-12-04 14:30:36 +0800978 // Get all the host of the subnet
979 Map<HostId, Host> hosts = hostsOfSubnet.get(routerInf.subnetId());
Sho SHIMIZUa09e1bb2016-08-01 14:25:25 -0700980 hosts.values().forEach(h -> {
lishuai858efd32015-12-04 14:30:36 +0800981 applyEastWestL3Flows(h, l3vni, operation);
982 });
983 }
984
lishuaibee5eca2016-05-10 19:17:37 +0800985 private void applyL3ArpFlows(DeviceId deviceId, VirtualPort gwPort,
986 Objective.Operation operation) {
987 IpAddress ip = null;
988 Iterator<FixedIp> gwIps = gwPort.fixedIps().iterator();
989 if (gwIps.hasNext()) {
990 ip = gwIps.next().ip();
991 }
992 IpAddress gwIp = ip;
993 MacAddress gwMac = gwPort.macAddress();
994 TenantNetwork network = tenantNetworkService
995 .getNetwork(gwPort.networkId());
996 if (deviceId != null) {
997 // Arp rules
998 DriverHandler handler = driverService.createHandler(deviceId);
999 arpService.programArpRules(handler, deviceId, gwIp,
1000 network.segmentationId(), gwMac,
1001 operation);
1002 } else {
1003 Iterable<Device> devices = deviceService.getAvailableDevices();
1004 Sets.newHashSet(devices).stream()
1005 .filter(d -> Device.Type.SWITCH == d.type()).forEach(d -> {
1006 // Arp rules
1007 DriverHandler handler = driverService.createHandler(d.id());
1008 arpService.programArpRules(handler, d.id(), gwIp,
1009 network.segmentationId(), gwMac,
1010 operation);
1011 });
1012 }
1013 }
1014
lishuai858efd32015-12-04 14:30:36 +08001015 private void applyEastWestL3Flows(Host h, SegmentationId l3vni,
1016 Objective.Operation operation) {
1017 if (!mastershipService.isLocalMaster(h.location().deviceId())) {
1018 log.debug("not master device:{}", h.location().deviceId());
1019 return;
1020 }
1021 String ifaceId = h.annotations().value(IFACEID);
1022 VirtualPort hPort = virtualPortService
1023 .getPort(VirtualPortId.portId(ifaceId));
1024 if (hPort == null) {
1025 hPort = VtnData.getPort(vPortStore, VirtualPortId.portId(ifaceId));
1026 }
1027 IpAddress srcIp = null;
1028 IpAddress srcGwIp = null;
1029 MacAddress srcVmGwMac = null;
1030 SubnetId srcSubnetId = null;
1031 Iterator<FixedIp> srcIps = hPort.fixedIps().iterator();
1032 if (srcIps.hasNext()) {
1033 FixedIp fixedIp = srcIps.next();
1034 srcIp = fixedIp.ip();
1035 srcSubnetId = fixedIp.subnetId();
1036 srcGwIp = subnetService.getSubnet(srcSubnetId).gatewayIp();
1037 FixedIp fixedGwIp = FixedIp.fixedIp(srcSubnetId, srcGwIp);
1038 VirtualPort gwPort = virtualPortService.getPort(fixedGwIp);
1039 if (gwPort == null) {
1040 gwPort = VtnData.getPort(vPortStore, fixedGwIp);
1041 }
1042 srcVmGwMac = gwPort.macAddress();
1043 }
1044 TenantNetwork network = tenantNetworkService
1045 .getNetwork(hPort.networkId());
lishuaibee5eca2016-05-10 19:17:37 +08001046 IpAddress dstVmIP = srcIp;
1047 MacAddress dstVmGwMac = srcVmGwMac;
1048 TenantId tenantId = hPort.tenantId();
lishuai858efd32015-12-04 14:30:36 +08001049 // Classifier rules
lishuaibee5eca2016-05-10 19:17:37 +08001050 if (operation == Objective.Operation.ADD) {
1051 sendEastWestL3Flows(h, srcVmGwMac, l3vni, srcGwIp, network,
1052 dstVmIP, dstVmGwMac, operation);
1053 } else if (operation == Objective.Operation.REMOVE) {
1054 FloatingIp floatingIp = null;
1055 Iterable<FloatingIp> floatingIps = floatingIpService.getFloatingIps();
1056 Set<FloatingIp> floatingIpSet = Sets.newHashSet(floatingIps).stream()
1057 .filter(f -> f.tenantId().equals(tenantId))
1058 .collect(Collectors.toSet());
1059 for (FloatingIp f : floatingIpSet) {
1060 IpAddress fixedIp = f.fixedIp();
1061 if (fixedIp != null && fixedIp.equals(srcIp)) {
1062 floatingIp = f;
1063 break;
1064 }
1065 }
1066 if (floatingIp == null) {
1067 sendEastWestL3Flows(h, srcVmGwMac, l3vni, srcGwIp, network,
1068 dstVmIP, dstVmGwMac, operation);
1069 }
1070 }
1071 }
1072
1073 private void sendEastWestL3Flows(Host h, MacAddress srcVmGwMac,
1074 SegmentationId l3vni, IpAddress srcGwIp,
1075 TenantNetwork network, IpAddress dstVmIP,
1076 MacAddress dstVmGwMac,
1077 Objective.Operation operation) {
lishuai858efd32015-12-04 14:30:36 +08001078 classifierService
1079 .programL3InPortClassifierRules(h.location().deviceId(),
1080 h.location().port(), h.mac(),
1081 srcVmGwMac, l3vni, operation);
lishuaibee5eca2016-05-10 19:17:37 +08001082 classifierService
1083 .programArpClassifierRules(h.location().deviceId(),
1084 h.location().port(), srcGwIp,
1085 network.segmentationId(), operation);
lishuai858efd32015-12-04 14:30:36 +08001086 Iterable<Device> devices = deviceService.getAvailableDevices();
lishuai858efd32015-12-04 14:30:36 +08001087 Sets.newHashSet(devices).stream()
1088 .filter(d -> Device.Type.SWITCH == d.type()).forEach(d -> {
1089 // L3FWD rules
lishuaibee5eca2016-05-10 19:17:37 +08001090 l3ForwardService.programRouteRules(d.id(), l3vni, dstVmIP,
lishuai858efd32015-12-04 14:30:36 +08001091 network.segmentationId(),
lishuaibee5eca2016-05-10 19:17:37 +08001092 dstVmGwMac, h.mac(),
lishuai858efd32015-12-04 14:30:36 +08001093 operation);
1094 });
1095 }
1096
1097 private void programFloatingIpEvent(VtnRscEventFeedback l3Feedback,
1098 VtnRscEvent.Type type) {
1099 FloatingIp floaingIp = l3Feedback.floatingIp();
1100 if (floaingIp != null) {
1101 VirtualPortId vmPortId = floaingIp.portId();
1102 VirtualPort vmPort = virtualPortService.getPort(vmPortId);
1103 VirtualPort fipPort = virtualPortService
1104 .getPort(floaingIp.networkId(), floaingIp.floatingIp());
1105 if (vmPort == null) {
1106 vmPort = VtnData.getPort(vPortStore, vmPortId);
1107 }
1108 if (fipPort == null) {
1109 fipPort = VtnData.getPort(vPortStore, floaingIp.networkId(),
1110 floaingIp.floatingIp());
1111 }
1112 Set<Host> hostSet = hostService.getHostsByMac(vmPort.macAddress());
1113 Host host = null;
1114 for (Host h : hostSet) {
1115 String ifaceid = h.annotations().value(IFACEID);
1116 if (ifaceid != null && ifaceid.equals(vmPortId.portId())) {
1117 host = h;
1118 break;
1119 }
1120 }
Ray Milkeyffe1a332018-01-24 10:41:14 -08001121 if (host != null && fipPort != null) {
lishuai858efd32015-12-04 14:30:36 +08001122 DeviceId deviceId = host.location().deviceId();
1123 Port exPort = exPortOfDevice.get(deviceId);
lishuai8798bbe2016-05-05 16:02:03 +08001124 TenantRouter tenantRouter = TenantRouter
1125 .tenantRouter(floaingIp.tenantId(), floaingIp.routerId());
1126 SegmentationId l3vni = vtnRscService.getL3vni(tenantRouter);
lishuai858efd32015-12-04 14:30:36 +08001127 // Floating ip BIND
lishuai762df812016-01-08 11:51:15 +08001128 if (type == VtnRscEvent.Type.FLOATINGIP_BIND) {
lishuai16c05af2016-01-21 18:39:05 +08001129 vPortStore.put(fipPort.portId(), fipPort);
lishuaibee5eca2016-05-10 19:17:37 +08001130 applyNorthSouthL3Flows(deviceId, false, tenantRouter, host,
1131 vmPort, fipPort, floaingIp, l3vni,
1132 exPort, Objective.Operation.ADD);
lishuai762df812016-01-08 11:51:15 +08001133 } else if (type == VtnRscEvent.Type.FLOATINGIP_UNBIND) {
lishuai858efd32015-12-04 14:30:36 +08001134 // Floating ip UNBIND
lishuaibee5eca2016-05-10 19:17:37 +08001135 applyNorthSouthL3Flows(deviceId, false, tenantRouter, host,
1136 vmPort, fipPort, floaingIp, l3vni,
1137 exPort,
lishuai858efd32015-12-04 14:30:36 +08001138 Objective.Operation.REMOVE);
lishuai16c05af2016-01-21 18:39:05 +08001139 vPortStore.remove(fipPort.portId());
lishuai858efd32015-12-04 14:30:36 +08001140 }
1141 }
1142 }
1143 }
1144
lishuaibee5eca2016-05-10 19:17:37 +08001145 private void sendNorthSouthL3Flows(DeviceId deviceId, FloatingIp floatingIp,
1146 IpAddress dstVmGwIp,
1147 MacAddress dstVmGwMac,
1148 SegmentationId l3vni,
1149 TenantNetwork vmNetwork,
1150 VirtualPort vmPort, Host host,
1151 Objective.Operation operation) {
1152 l3ForwardService
1153 .programRouteRules(deviceId, l3vni, floatingIp.fixedIp(),
1154 vmNetwork.segmentationId(), dstVmGwMac,
1155 vmPort.macAddress(), operation);
1156 classifierService.programL3InPortClassifierRules(deviceId,
1157 host.location().port(),
1158 host.mac(), dstVmGwMac,
1159 l3vni, operation);
1160 classifierService.programArpClassifierRules(deviceId, host.location()
1161 .port(), dstVmGwIp, vmNetwork.segmentationId(), operation);
1162 }
1163
1164 private void applyNorthSouthL3Flows(DeviceId deviceId, boolean hostFlag,
1165 TenantRouter tenantRouter, Host host,
lishuai858efd32015-12-04 14:30:36 +08001166 VirtualPort vmPort, VirtualPort fipPort,
1167 FloatingIp floatingIp,
lishuai8798bbe2016-05-05 16:02:03 +08001168 SegmentationId l3vni, Port exPort,
lishuai858efd32015-12-04 14:30:36 +08001169 Objective.Operation operation) {
1170 if (!mastershipService.isLocalMaster(deviceId)) {
1171 log.debug("not master device:{}", deviceId);
1172 return;
1173 }
1174 List gwIpMac = getGwIpAndMac(vmPort);
1175 IpAddress dstVmGwIp = (IpAddress) gwIpMac.get(0);
1176 MacAddress dstVmGwMac = (MacAddress) gwIpMac.get(1);
lishuai858efd32015-12-04 14:30:36 +08001177 TenantNetwork vmNetwork = tenantNetworkService
1178 .getNetwork(vmPort.networkId());
1179 TenantNetwork fipNetwork = tenantNetworkService
1180 .getNetwork(fipPort.networkId());
1181 // L3 downlink traffic flow
lishuaia3e32342015-12-07 10:59:17 +08001182 MacAddress exPortMac = MacAddress.valueOf(exPort.annotations()
1183 .value(AnnotationKeys.PORT_MAC));
lishuai858efd32015-12-04 14:30:36 +08001184 classifierService.programL3ExPortClassifierRules(deviceId, exPort.number(),
1185 floatingIp.floatingIp(), operation);
lishuai858efd32015-12-04 14:30:36 +08001186 dnatService.programRules(deviceId, floatingIp.floatingIp(),
Bob zhou59a21062016-05-12 19:40:05 +08001187 exPortMac, floatingIp.fixedIp(),
lishuai8798bbe2016-05-05 16:02:03 +08001188 l3vni, operation);
lishuai858efd32015-12-04 14:30:36 +08001189
Bob zhou59a21062016-05-12 19:40:05 +08001190 Subnet subnet = getSubnetOfFloatingIP(floatingIp);
1191 IpPrefix ipPrefix = subnet.cidr();
1192 snatService.programSnatSameSegmentUploadControllerRules(deviceId, l3vni,
1193 floatingIp.fixedIp(),
1194 floatingIp.floatingIp(),
1195 ipPrefix,
1196 operation);
lishuai858efd32015-12-04 14:30:36 +08001197 // L3 uplink traffic flow
lishuaibee5eca2016-05-10 19:17:37 +08001198 if (operation == Objective.Operation.ADD) {
1199 sendNorthSouthL3Flows(deviceId, floatingIp, dstVmGwIp, dstVmGwMac,
1200 l3vni, vmNetwork, vmPort, host, operation);
Bob zhou59a21062016-05-12 19:40:05 +08001201 l2ForwardService
1202 .programExternalOut(deviceId, fipNetwork.segmentationId(),
1203 exPort.number(), exPortMac, operation);
lishuaibee5eca2016-05-10 19:17:37 +08001204 } else if (operation == Objective.Operation.REMOVE) {
Ray Milkeyffe1a332018-01-24 10:41:14 -08001205 if (hostFlag || (routerInfFlagOfTenantRouter.get(tenantRouter) == null)) {
lishuaibee5eca2016-05-10 19:17:37 +08001206 sendNorthSouthL3Flows(deviceId, floatingIp, dstVmGwIp, dstVmGwMac,
1207 l3vni, vmNetwork, vmPort, host, operation);
1208 }
1209 Iterable<FloatingIp> floatingIps = floatingIpService.getFloatingIps();
1210 boolean exPortFlag = true;
1211 if (floatingIps != null) {
1212 Set<FloatingIp> floatingIpSet = Sets.newHashSet(floatingIps);
1213 for (FloatingIp fip : floatingIpSet) {
1214 if (fip.fixedIp() != null) {
1215 exPortFlag = false;
1216 break;
1217 }
1218 }
1219 }
1220 if (exPortFlag) {
Bob zhou59a21062016-05-12 19:40:05 +08001221 l2ForwardService.programExternalOut(deviceId,
1222 fipNetwork.segmentationId(),
1223 exPort.number(), exPortMac,
1224 operation);
lishuaibee5eca2016-05-10 19:17:37 +08001225 }
Bob zhou59a21062016-05-12 19:40:05 +08001226 removeRulesInSnat(deviceId, floatingIp.fixedIp());
lishuaibee5eca2016-05-10 19:17:37 +08001227 }
lishuai858efd32015-12-04 14:30:36 +08001228 }
1229
1230 private Port getExPort(DeviceId deviceId) {
1231 List<Port> ports = deviceService.getPorts(deviceId);
1232 Port exPort = null;
1233 for (Port port : ports) {
1234 String portName = port.annotations().value(AnnotationKeys.PORT_NAME);
lishuaib43dbf72016-01-06 11:11:35 +08001235 Versioned<String> exPortVersioned = exPortMap.get(EX_PORT_KEY);
1236 if (portName != null && exPortVersioned != null && portName.
1237 equals(exPortVersioned.value())) {
lishuai858efd32015-12-04 14:30:36 +08001238 exPort = port;
1239 break;
1240 }
1241 }
1242 return exPort;
1243 }
1244
1245 private List getGwIpAndMac(VirtualPort port) {
1246 List list = new ArrayList();
1247 MacAddress gwMac = null;
1248 SubnetId subnetId = null;
1249 IpAddress gwIp = null;
1250 Iterator<FixedIp> fixips = port.fixedIps().iterator();
1251 if (fixips.hasNext()) {
1252 FixedIp fixip = fixips.next();
1253 subnetId = fixip.subnetId();
1254 gwIp = subnetService.getSubnet(subnetId).gatewayIp();
1255 FixedIp fixedGwIp = FixedIp.fixedIp(fixip.subnetId(), gwIp);
1256 VirtualPort gwPort = virtualPortService.getPort(fixedGwIp);
1257 if (gwPort == null) {
1258 gwPort = VtnData.getPort(vPortStore, fixedGwIp);
1259 }
1260 gwMac = gwPort.macAddress();
1261 }
1262 list.add(gwIp);
1263 list.add(gwMac);
1264 return list;
1265 }
1266
lishuai858efd32015-12-04 14:30:36 +08001267 private void applyHostMonitoredL3Rules(Host host,
1268 Objective.Operation operation) {
1269 String ifaceId = host.annotations().value(IFACEID);
1270 DeviceId deviceId = host.location().deviceId();
1271 VirtualPortId portId = VirtualPortId.portId(ifaceId);
1272 VirtualPort port = virtualPortService.getPort(portId);
1273 if (port == null) {
1274 port = VtnData.getPort(vPortStore, portId);
1275 }
1276 TenantId tenantId = port.tenantId();
1277 Port exPort = exPortOfDevice.get(deviceId);
lishuai858efd32015-12-04 14:30:36 +08001278 Iterator<FixedIp> fixips = port.fixedIps().iterator();
1279 SubnetId sid = null;
1280 IpAddress hostIp = null;
1281 if (fixips.hasNext()) {
1282 FixedIp fixip = fixips.next();
1283 sid = fixip.subnetId();
1284 hostIp = fixip.ip();
1285 }
1286 final SubnetId subnetId = sid;
1287 // L3 internal network access to each other
1288 Iterable<RouterInterface> interfaces = routerInterfaceService
1289 .getRouterInterfaces();
lishuai8798bbe2016-05-05 16:02:03 +08001290 Set<RouterInterface> hostInterfaces = Sets.newHashSet(interfaces)
lishuai858efd32015-12-04 14:30:36 +08001291 .stream().filter(r -> r.tenantId().equals(tenantId))
lishuai8798bbe2016-05-05 16:02:03 +08001292 .filter(r -> r.subnetId().equals(subnetId))
lishuai858efd32015-12-04 14:30:36 +08001293 .collect(Collectors.toSet());
Sho SHIMIZUa09e1bb2016-08-01 14:25:25 -07001294 hostInterfaces.forEach(routerInf -> {
lishuai8798bbe2016-05-05 16:02:03 +08001295 Set<RouterInterface> interfacesSet = Sets.newHashSet(interfaces)
1296 .stream().filter(r -> r.tenantId().equals(tenantId))
1297 .filter(r -> r.routerId().equals(routerInf.routerId()))
1298 .collect(Collectors.toSet());
1299 long count = interfacesSet.stream()
1300 .filter(r -> !r.subnetId().equals(subnetId)).count();
1301 if (count > 0) {
1302 TenantRouter tenantRouter = TenantRouter
1303 .tenantRouter(routerInf.tenantId(), routerInf.routerId());
1304 SegmentationId l3vni = vtnRscService.getL3vni(tenantRouter);
1305 if (operation == Objective.Operation.ADD) {
1306 if (routerInfFlagOfTenantRouter.get(tenantRouter) != null) {
1307 applyEastWestL3Flows(host, l3vni, operation);
1308 } else {
1309 if (interfacesSet.size() > 1) {
1310 programInterfacesSet(interfacesSet, operation);
1311 }
1312 }
1313 } else if (operation == Objective.Operation.REMOVE) {
1314 if (routerInfFlagOfTenantRouter.get(tenantRouter) != null) {
1315 applyEastWestL3Flows(host, l3vni, operation);
lishuai858efd32015-12-04 14:30:36 +08001316 }
1317 }
lishuai858efd32015-12-04 14:30:36 +08001318 }
lishuai8798bbe2016-05-05 16:02:03 +08001319 });
lishuai858efd32015-12-04 14:30:36 +08001320 // L3 external and internal network access to each other
1321 FloatingIp floatingIp = null;
1322 Iterable<FloatingIp> floatingIps = floatingIpService.getFloatingIps();
1323 Set<FloatingIp> floatingIpSet = Sets.newHashSet(floatingIps).stream()
1324 .filter(f -> f.tenantId().equals(tenantId))
1325 .collect(Collectors.toSet());
1326 for (FloatingIp f : floatingIpSet) {
1327 IpAddress fixedIp = f.fixedIp();
lishuaibee5eca2016-05-10 19:17:37 +08001328 if (fixedIp != null && fixedIp.equals(hostIp)) {
lishuai858efd32015-12-04 14:30:36 +08001329 floatingIp = f;
1330 break;
1331 }
1332 }
1333 if (floatingIp != null) {
lishuai8798bbe2016-05-05 16:02:03 +08001334 TenantRouter tenantRouter = TenantRouter
1335 .tenantRouter(floatingIp.tenantId(), floatingIp.routerId());
1336 SegmentationId l3vni = vtnRscService.getL3vni(tenantRouter);
lishuai858efd32015-12-04 14:30:36 +08001337 VirtualPort fipPort = virtualPortService
1338 .getPort(floatingIp.networkId(), floatingIp.floatingIp());
1339 if (fipPort == null) {
1340 fipPort = VtnData.getPort(vPortStore, floatingIp.networkId(),
1341 floatingIp.floatingIp());
1342 }
lishuaibee5eca2016-05-10 19:17:37 +08001343 applyNorthSouthL3Flows(deviceId, true, tenantRouter, host, port,
1344 fipPort, floatingIp, l3vni, exPort,
1345 operation);
lishuai858efd32015-12-04 14:30:36 +08001346 }
1347 }
lishuai74f2d532015-12-10 17:03:34 +08001348
1349 public static void setExPortName(String name) {
lishuaib43dbf72016-01-06 11:11:35 +08001350 exPortMap.put(EX_PORT_KEY, name);
lishuai74f2d532015-12-10 17:03:34 +08001351 }
Bob zhou59a21062016-05-12 19:40:05 +08001352
1353 /**
1354 * Packet processor responsible for forwarding packets along their paths.
1355 */
1356 private class VtnL3PacketProcessor implements PacketProcessor {
1357
1358 @Override
1359 public void process(PacketContext context) {
1360 InboundPacket pkt = context.inPacket();
1361 ConnectPoint connectPoint = pkt.receivedFrom();
1362 DeviceId deviceId = connectPoint.deviceId();
1363 Ethernet ethPkt = pkt.parsed();
1364 if (ethPkt == null) {
1365 return;
1366 }
1367 if (ethPkt.getEtherType() == Ethernet.TYPE_ARP) {
1368 ARP arpPacket = (ARP) ethPkt.getPayload();
1369 if ((arpPacket.getOpCode() == ARP.OP_REQUEST)) {
1370 arprequestProcess(arpPacket, deviceId);
1371 } else if (arpPacket.getOpCode() == ARP.OP_REPLY) {
1372 arpresponceProcess(arpPacket, deviceId);
1373 }
1374 } else if (ethPkt.getEtherType() == Ethernet.TYPE_IPV4) {
1375 if (ethPkt.getDestinationMAC().isMulticast()) {
1376 return;
1377 }
1378 IPv4 ip = (IPv4) ethPkt.getPayload();
1379 upStreamPacketProcessor(ip, deviceId);
1380
1381 } else {
1382 return;
1383 }
1384 }
1385
1386 private void arprequestProcess(ARP arpPacket, DeviceId deviceId) {
1387 MacAddress dstMac = MacAddress
1388 .valueOf(arpPacket.getSenderHardwareAddress());
1389 IpAddress srcIp = IpAddress.valueOf(IPv4
1390 .toIPv4Address(arpPacket.getTargetProtocolAddress()));
1391 IpAddress dstIp = IpAddress.valueOf(IPv4
1392 .toIPv4Address(arpPacket.getSenderProtocolAddress()));
1393 FloatingIp floatingIp = floatingIpStore.get(srcIp);
1394 if (floatingIp == null) {
1395 return;
1396 }
1397 DeviceId deviceIdOfFloatingIp = getDeviceIdOfFloatingIP(floatingIp);
1398 if (!deviceId.equals(deviceIdOfFloatingIp)) {
1399 return;
1400 }
1401 Port exPort = exPortOfDevice.get(deviceId);
1402 MacAddress srcMac = MacAddress.valueOf(exPort.annotations()
1403 .value(AnnotationKeys.PORT_MAC));
1404 if (!downloadSnatRules(deviceId, srcMac, srcIp, dstMac, dstIp,
1405 floatingIp)) {
1406 return;
1407 }
1408 Ethernet ethernet = buildArpResponse(dstIp, dstMac, srcIp, srcMac);
1409 if (ethernet != null) {
1410 sendPacketOut(deviceId, exPort.number(), ethernet);
1411 }
1412 }
1413
1414 private void arpresponceProcess(ARP arpPacket, DeviceId deviceId) {
1415 MacAddress srcMac = MacAddress
1416 .valueOf(arpPacket.getTargetHardwareAddress());
1417 MacAddress dstMac = MacAddress
1418 .valueOf(arpPacket.getSenderHardwareAddress());
1419 IpAddress srcIp = IpAddress.valueOf(IPv4
1420 .toIPv4Address(arpPacket.getTargetProtocolAddress()));
1421 IpAddress dstIp = IpAddress.valueOf(IPv4
1422 .toIPv4Address(arpPacket.getSenderProtocolAddress()));
1423 FloatingIp floatingIp = floatingIpStore.get(srcIp);
1424 if (floatingIp == null) {
1425 return;
1426 }
1427 DeviceId deviceIdOfFloatingIp = getDeviceIdOfFloatingIP(floatingIp);
1428 if (!deviceId.equals(deviceIdOfFloatingIp)) {
1429 return;
1430 }
1431 if (!downloadSnatRules(deviceId, srcMac, srcIp, dstMac, dstIp,
1432 floatingIp)) {
1433 return;
1434 }
1435 }
1436
1437 private void upStreamPacketProcessor(IPv4 ipPacket, DeviceId deviceId) {
1438 IpAddress srcIp = IpAddress.valueOf(ipPacket.getSourceAddress());
1439 IpAddress dstIp = IpAddress.valueOf(ipPacket.getDestinationAddress());
1440 FloatingIp floatingIp = null;
1441 Collection<FloatingIp> floatingIps = floatingIpService
1442 .getFloatingIps();
1443 Set<FloatingIp> floatingIpSet = Sets.newHashSet(floatingIps)
1444 .stream().collect(Collectors.toSet());
1445 for (FloatingIp f : floatingIpSet) {
1446 IpAddress fixIp = f.fixedIp();
1447 if (fixIp != null && fixIp.equals(srcIp)) {
1448 floatingIp = f;
1449 break;
1450 }
1451 }
1452 if (floatingIp == null) {
1453 return;
1454 }
1455 Subnet subnet = getSubnetOfFloatingIP(floatingIp);
1456 IpAddress gwIp = subnet.gatewayIp();
1457 Port exportPort = exPortOfDevice.get(deviceId);
1458 MacAddress exPortMac = MacAddress.valueOf(exportPort.annotations()
1459 .value(AnnotationKeys.PORT_MAC));
1460 IpPrefix ipPrefix = subnet.cidr();
1461 if (ipPrefix == null) {
1462 return;
1463 }
1464 int mask = ipPrefix.prefixLength();
1465 if (mask <= 0) {
1466 return;
1467 }
1468 Ethernet ethernet = null;
1469 // if the same ip segment
1470 if (IpUtil.checkSameSegment(floatingIp.floatingIp(), dstIp, mask)) {
1471 ethernet = buildArpRequest(dstIp, floatingIp.floatingIp(),
1472 exPortMac);
1473 } else {
1474 ethernet = buildArpRequest(gwIp, floatingIp.floatingIp(),
1475 exPortMac);
1476 }
1477 if (ethernet != null) {
1478 sendPacketOut(deviceId, exportPort.number(), ethernet);
1479 }
1480 }
1481 }
1482
1483 private Ethernet buildArpRequest(IpAddress targetIp, IpAddress sourceIp,
1484 MacAddress sourceMac) {
1485 ARP arp = new ARP();
1486 arp.setHardwareType(ARP.HW_TYPE_ETHERNET)
1487 .setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH)
1488 .setProtocolType(ARP.PROTO_TYPE_IP)
1489 .setProtocolAddressLength((byte) Ip4Address.BYTE_LENGTH)
1490 .setOpCode(ARP.OP_REQUEST);
1491
1492 arp.setSenderHardwareAddress(sourceMac.toBytes())
1493 .setSenderProtocolAddress(sourceIp.getIp4Address().toInt())
1494 .setTargetHardwareAddress(ZERO_MAC_ADDRESS)
1495 .setTargetProtocolAddress(targetIp.getIp4Address().toInt());
1496
1497 Ethernet ethernet = new Ethernet();
1498 ethernet.setEtherType(Ethernet.TYPE_ARP)
1499 .setDestinationMACAddress(MacAddress.BROADCAST)
1500 .setSourceMACAddress(sourceMac)
1501 .setPayload(arp);
1502
1503 ethernet.setPad(true);
1504 return ethernet;
1505 }
1506
1507 private Ethernet buildArpResponse(IpAddress targetIp, MacAddress targetMac,
1508 IpAddress sourceIp, MacAddress sourceMac) {
1509 ARP arp = new ARP();
1510 arp.setHardwareType(ARP.HW_TYPE_ETHERNET)
1511 .setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH)
1512 .setProtocolType(ARP.PROTO_TYPE_IP)
1513 .setProtocolAddressLength((byte) Ip4Address.BYTE_LENGTH)
1514 .setOpCode(ARP.OP_REPLY);
1515
1516 arp.setSenderHardwareAddress(sourceMac.toBytes())
1517 .setSenderProtocolAddress(sourceIp.getIp4Address().toInt())
1518 .setTargetHardwareAddress(targetMac.toBytes())
1519 .setTargetProtocolAddress(targetIp.getIp4Address().toInt());
1520
1521 Ethernet ethernet = new Ethernet();
1522 ethernet.setEtherType(Ethernet.TYPE_ARP)
1523 .setDestinationMACAddress(targetMac)
1524 .setSourceMACAddress(sourceMac)
1525 .setPayload(arp);
1526
1527 ethernet.setPad(true);
1528
1529 return ethernet;
1530 }
1531
1532 private void sendPacketOut(DeviceId deviceId, PortNumber portNumber,
1533 Ethernet payload) {
1534 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
1535 .setOutput(portNumber).build();
1536 OutboundPacket packet = new DefaultOutboundPacket(deviceId, treatment,
1537 ByteBuffer
1538 .wrap(payload
1539 .serialize()));
1540 packetService.emit(packet);
1541 }
1542
1543 private Subnet getSubnetOfFloatingIP(FloatingIp floatingIp) {
1544 DeviceId exVmPortId = DeviceId
1545 .deviceId(floatingIp.id().floatingIpId().toString());
1546 Collection<VirtualPort> exVmPortList = virtualPortService
1547 .getPorts(exVmPortId);
1548 VirtualPort exVmPort = null;
1549 if (exVmPortList != null) {
1550 exVmPort = exVmPortList.iterator().next();
1551 }
1552 if (exVmPort == null) {
sdna0138f52018-06-12 19:41:35 +09001553 log.debug("exVM Port is null {}.", floatingIp);
Bob zhou59a21062016-05-12 19:40:05 +08001554 return null;
1555 }
1556 Set<FixedIp> fixedIps = exVmPort.fixedIps();
1557 SubnetId subnetId = null;
1558 for (FixedIp f : fixedIps) {
1559 IpAddress fp = f.ip();
1560 if (fp.equals(floatingIp.floatingIp())) {
1561 subnetId = f.subnetId();
1562 break;
1563 }
1564 }
1565 if (subnetId == null) {
sdna0138f52018-06-12 19:41:35 +09001566 log.debug("subnetId is null {}.", floatingIp);
Bob zhou59a21062016-05-12 19:40:05 +08001567 return null;
1568 }
1569 Subnet subnet = subnetService.getSubnet(subnetId);
1570 return subnet;
1571 }
1572
1573 private DeviceId getDeviceIdOfFloatingIP(FloatingIp floatingIp) {
1574 VirtualPortId vmPortId = floatingIp.portId();
1575 VirtualPort vmPort = virtualPortService.getPort(vmPortId);
1576 if (vmPort == null) {
1577 vmPort = VtnData.getPort(vPortStore, vmPortId);
1578 }
1579 Set<Host> hostSet = hostService.getHostsByMac(vmPort.macAddress());
1580 Host host = null;
1581 for (Host h : hostSet) {
1582 String ifaceid = h.annotations().value(IFACEID);
1583 if (ifaceid != null && ifaceid.equals(vmPortId.portId())) {
1584 host = h;
1585 break;
1586 }
1587 }
1588 if (host == null) {
sdna0138f52018-06-12 19:41:35 +09001589 log.debug("Host is null {}.", floatingIp);
Bob zhou59a21062016-05-12 19:40:05 +08001590 return null;
1591 } else {
1592 return host.location().deviceId();
1593 }
1594 }
1595
1596 private boolean downloadSnatRules(DeviceId deviceId, MacAddress srcMac,
1597 IpAddress srcIp, MacAddress dstMac,
1598 IpAddress dstIp, FloatingIp floatingIp) {
1599 TenantNetwork exNetwork = tenantNetworkService
1600 .getNetwork(floatingIp.networkId());
1601 IpAddress fixedIp = floatingIp.fixedIp();
1602 VirtualPortId vmPortId = floatingIp.portId();
1603 VirtualPort vmPort = virtualPortService.getPort(vmPortId);
1604 if (vmPort == null) {
1605 vmPort = VtnData.getPort(vPortStore, vmPortId);
1606 }
1607 Subnet subnet = getSubnetOfFloatingIP(floatingIp);
1608 IpPrefix ipPrefix = subnet.cidr();
1609 IpAddress gwIp = subnet.gatewayIp();
1610 if (ipPrefix == null) {
1611 return false;
1612 }
1613 int mask = ipPrefix.prefixLength();
1614 if (mask <= 0) {
1615 return false;
1616 }
1617 TenantRouter tenantRouter = TenantRouter
1618 .tenantRouter(floatingIp.tenantId(), floatingIp.routerId());
1619 SegmentationId l3vni = vtnRscService.getL3vni(tenantRouter);
1620 // if the same ip segment
1621 if (IpUtil.checkSameSegment(srcIp, dstIp, mask)) {
1622 snatService.programSnatSameSegmentRules(deviceId, l3vni, fixedIp,
1623 dstIp, dstMac, srcMac,
1624 srcIp,
1625 exNetwork.segmentationId(),
1626 Objective.Operation.ADD);
1627 if (dstIp.equals(gwIp)) {
1628 snatService
1629 .programSnatDiffSegmentRules(deviceId, l3vni, fixedIp,
1630 dstMac, srcMac, srcIp,
1631 exNetwork.segmentationId(),
1632 Objective.Operation.ADD);
1633 }
1634 }
1635 return true;
1636 }
1637
1638 private void removeRulesInSnat(DeviceId deviceId, IpAddress fixedIp) {
1639 for (FlowEntry f : flowRuleService.getFlowEntries(deviceId)) {
1640 if (f.tableId() == SNAT_TABLE
1641 && f.priority() > SNAT_DEFAULT_RULE_PRIORITY) {
1642 String srcIp = f.selector()
1643 .getCriterion(Criterion.Type.IPV4_SRC).toString();
1644 int priority = f.priority();
1645 if (srcIp != null && srcIp.contains(fixedIp.toString())) {
1646 log.info("Match snat rules bob");
1647 TrafficSelector selector = f.selector();
1648 TrafficTreatment treatment = f.treatment();
1649 snatService.removeSnatRules(deviceId, selector, treatment,
1650 priority,
1651 Objective.Operation.REMOVE);
1652
1653 }
1654 }
1655 }
1656 }
lishuai6c56f5e2015-11-17 16:38:19 +08001657}