blob: 1dc094b6a995d537bd656d55401bff33755c105b [file] [log] [blame]
Hyunsun Moond0e932a2015-09-15 22:39:16 -07001/*
2 * Copyright 2014-2015 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.cordvtn;
17
Hyunsun Moon1f145552015-10-08 22:25:30 -070018import com.google.common.collect.Sets;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070019import org.apache.felix.scr.annotations.Activate;
20import org.apache.felix.scr.annotations.Component;
21import org.apache.felix.scr.annotations.Deactivate;
22import org.apache.felix.scr.annotations.Reference;
23import org.apache.felix.scr.annotations.ReferenceCardinality;
24import org.apache.felix.scr.annotations.Service;
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -080025import org.onlab.packet.Ethernet;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080026import org.onlab.packet.IpAddress;
Hyunsun Moonb77b60f2016-01-15 20:03:18 -080027import org.onlab.packet.MacAddress;
28import org.onlab.packet.VlanId;
Hyunsun Moon1f145552015-10-08 22:25:30 -070029import org.onosproject.core.ApplicationId;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070030import org.onosproject.core.CoreService;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080031import org.onosproject.mastership.MastershipService;
Hyunsun Moonb77b60f2016-01-15 20:03:18 -080032import org.onosproject.net.ConnectPoint;
Hyunsun Moond772f342015-10-28 20:28:16 -070033import org.onosproject.net.DefaultAnnotations;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070034import org.onosproject.net.Host;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080035import org.onosproject.net.HostId;
Hyunsun Moonb77b60f2016-01-15 20:03:18 -080036import org.onosproject.net.HostLocation;
Hyunsun Moon8539b042015-11-07 22:08:43 -080037import org.onosproject.net.Port;
Hyunsun Moonb77b60f2016-01-15 20:03:18 -080038import org.onosproject.net.SparseAnnotations;
Hyunsun Moon746956f2016-01-24 21:47:06 -080039import org.onosproject.net.config.ConfigFactory;
40import org.onosproject.net.config.NetworkConfigEvent;
41import org.onosproject.net.config.NetworkConfigListener;
42import org.onosproject.net.config.NetworkConfigRegistry;
43import org.onosproject.net.config.NetworkConfigService;
44import org.onosproject.net.config.basics.SubjectFactories;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070045import org.onosproject.net.device.DeviceService;
Hyunsun Moond772f342015-10-28 20:28:16 -070046import org.onosproject.net.driver.DriverService;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080047import org.onosproject.net.flow.FlowRuleService;
48import org.onosproject.net.group.GroupService;
Hyunsun Moonb77b60f2016-01-15 20:03:18 -080049import org.onosproject.net.host.DefaultHostDescription;
50import org.onosproject.net.host.HostDescription;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070051import org.onosproject.net.host.HostEvent;
52import org.onosproject.net.host.HostListener;
Hyunsun Moonb77b60f2016-01-15 20:03:18 -080053import org.onosproject.net.host.HostProvider;
54import org.onosproject.net.host.HostProviderRegistry;
55import org.onosproject.net.host.HostProviderService;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070056import org.onosproject.net.host.HostService;
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -080057import org.onosproject.net.packet.PacketContext;
58import org.onosproject.net.packet.PacketProcessor;
59import org.onosproject.net.packet.PacketService;
Hyunsun Moonb77b60f2016-01-15 20:03:18 -080060import org.onosproject.net.provider.AbstractProvider;
61import org.onosproject.net.provider.ProviderId;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080062import org.onosproject.openstackswitching.OpenstackNetwork;
63import org.onosproject.openstackswitching.OpenstackPort;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080064import org.onosproject.openstackswitching.OpenstackSubnet;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080065import org.onosproject.openstackswitching.OpenstackSwitchingService;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070066import org.slf4j.Logger;
67
Hyunsun Moon1f145552015-10-08 22:25:30 -070068import java.util.Map;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080069import java.util.Set;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070070import java.util.concurrent.ExecutorService;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080071import java.util.stream.Collectors;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070072
Hyunsun Moon1f145552015-10-08 22:25:30 -070073import static com.google.common.base.Preconditions.checkNotNull;
Hyunsun Moon746956f2016-01-24 21:47:06 -080074import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070075import static org.onlab.util.Tools.groupedThreads;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070076import static org.slf4j.LoggerFactory.getLogger;
77
78/**
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080079 * Provisions virtual tenant networks with service chaining capability
80 * in OpenStack environment.
Hyunsun Moond0e932a2015-09-15 22:39:16 -070081 */
82@Component(immediate = true)
83@Service
Hyunsun Moonb77b60f2016-01-15 20:03:18 -080084public class CordVtn extends AbstractProvider implements CordVtnService, HostProvider {
Hyunsun Moond0e932a2015-09-15 22:39:16 -070085
86 protected final Logger log = getLogger(getClass());
87
88 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
89 protected CoreService coreService;
90
91 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon746956f2016-01-24 21:47:06 -080092 protected NetworkConfigRegistry configRegistry;
93
94 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
95 protected NetworkConfigService configService;
96
97 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonb77b60f2016-01-15 20:03:18 -080098 protected HostProviderRegistry hostProviderRegistry;
Hyunsun Moond0e932a2015-09-15 22:39:16 -070099
100 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700101 protected DeviceService deviceService;
102
103 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
104 protected HostService hostService;
105
Hyunsun Moon1f145552015-10-08 22:25:30 -0700106 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moond772f342015-10-28 20:28:16 -0700107 protected DriverService driverService;
108
109 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800110 protected FlowRuleService flowRuleService;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800111
112 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800113 protected PacketService packetService;
114
115 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800116 protected MastershipService mastershipService;
117
118 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
119 protected GroupService groupService;
120
121 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800122 protected OpenstackSwitchingService openstackService;
123
Hyunsun Moon746956f2016-01-24 21:47:06 -0800124 private final ConfigFactory configFactory =
125 new ConfigFactory(SubjectFactories.APP_SUBJECT_FACTORY, CordVtnConfig.class, "cordvtn") {
126 @Override
127 public CordVtnConfig createConfig() {
128 return new CordVtnConfig();
129 }
130 };
131
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800132 private static final String DEFAULT_TUNNEL = "vxlan";
133 private static final String SERVICE_ID = "serviceId";
134 private static final String LOCATION_IP = "locationIp";
135 private static final String OPENSTACK_VM_ID = "openstackVmId";
136
Hyunsun Moon746956f2016-01-24 21:47:06 -0800137 private final ExecutorService eventExecutor =
138 newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn", "event-handler"));
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700139
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800140 private final PacketProcessor packetProcessor = new InternalPacketProcessor();
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800141 private final HostListener hostListener = new InternalHostListener();
Hyunsun Moon746956f2016-01-24 21:47:06 -0800142 private final NetworkConfigListener configListener = new InternalConfigListener();
Hyunsun Moon2b530322015-09-23 13:24:35 -0700143
Hyunsun Moon746956f2016-01-24 21:47:06 -0800144 private ApplicationId appId;
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800145 private HostProviderService hostProvider;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800146 private CordVtnRuleInstaller ruleInstaller;
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800147 private CordVtnArpProxy arpProxy;
Hyunsun Moon746956f2016-01-24 21:47:06 -0800148 private volatile MacAddress gatewayMac = MacAddress.NONE;
Hyunsun Moon8539b042015-11-07 22:08:43 -0800149
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800150 /**
151 * Creates an cordvtn host location provider.
152 */
153 public CordVtn() {
154 super(new ProviderId("host", CORDVTN_APP_ID));
Hyunsun Moon8539b042015-11-07 22:08:43 -0800155 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700156
157 @Activate
158 protected void activate() {
Hyunsun Moon746956f2016-01-24 21:47:06 -0800159 appId = coreService.registerApplication("org.onosproject.cordvtn");
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800160 ruleInstaller = new CordVtnRuleInstaller(appId, flowRuleService,
161 deviceService,
162 driverService,
163 groupService,
164 mastershipService,
165 DEFAULT_TUNNEL);
166
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800167 arpProxy = new CordVtnArpProxy(appId, packetService);
168 packetService.addProcessor(packetProcessor, PacketProcessor.director(0));
169 arpProxy.requestPacket();
170
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700171 hostService.addListener(hostListener);
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800172 hostProvider = hostProviderRegistry.register(this);
Hyunsun Moon2b530322015-09-23 13:24:35 -0700173
Hyunsun Moon746956f2016-01-24 21:47:06 -0800174 configRegistry.registerConfigFactory(configFactory);
175 configService.addListener(configListener);
176 readConfiguration();
177
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700178 log.info("Started");
179 }
180
181 @Deactivate
182 protected void deactivate() {
Hyunsun Moon746956f2016-01-24 21:47:06 -0800183 hostProviderRegistry.unregister(this);
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700184 hostService.removeListener(hostListener);
Hyunsun Moon746956f2016-01-24 21:47:06 -0800185
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800186 packetService.removeProcessor(packetProcessor);
Hyunsun Moon2b530322015-09-23 13:24:35 -0700187
Hyunsun Moon746956f2016-01-24 21:47:06 -0800188 configRegistry.unregisterConfigFactory(configFactory);
189 configService.removeListener(configListener);
Hyunsun Moon2b530322015-09-23 13:24:35 -0700190
Hyunsun Moon746956f2016-01-24 21:47:06 -0800191 eventExecutor.shutdown();
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700192 log.info("Stopped");
193 }
194
195 @Override
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800196 public void triggerProbe(Host host) {
197 /*
198 * Note: In CORD deployment, we assume that all hosts are configured.
199 * Therefore no probe is required.
200 */
Hyunsun Moonb219fc42016-01-14 03:42:47 -0800201 }
202
203 @Override
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800204 public void createServiceDependency(CordServiceId tServiceId, CordServiceId pServiceId) {
205 CordService tService = getCordService(tServiceId);
206 CordService pService = getCordService(pServiceId);
Hyunsun Moonbfc47d12015-12-07 14:06:28 -0800207
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800208 if (tService == null || pService == null) {
209 log.error("Failed to create CordService for {}", tServiceId.id());
210 return;
211 }
212
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800213 log.info("Service dependency from {} to {} created.", tService.id().id(), pService.id().id());
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800214 ruleInstaller.populateServiceDependencyRules(tService, pService);
Hyunsun Moon699f46b2015-12-04 11:35:25 -0800215 }
216
217 @Override
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800218 public void removeServiceDependency(CordServiceId tServiceId, CordServiceId pServiceId) {
219 CordService tService = getCordService(tServiceId);
220 CordService pService = getCordService(pServiceId);
Hyunsun Moonbfc47d12015-12-07 14:06:28 -0800221
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800222 if (tService == null || pService == null) {
223 log.error("Failed to create CordService for {}", tServiceId.id());
224 return;
225 }
226
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800227 log.info("Service dependency from {} to {} removed.", tService.id().id(), pService.id().id());
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800228 ruleInstaller.removeServiceDependencyRules(tService, pService);
Hyunsun Moon699f46b2015-12-04 11:35:25 -0800229 }
230
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800231 @Override
232 public void addServiceVm(CordVtnNode node, ConnectPoint connectPoint) {
233 Port port = deviceService.getPort(connectPoint.deviceId(), connectPoint.port());
234 OpenstackPort vPort = openstackService.port(port);
235 if (vPort == null) {
236 log.warn("Failed to get OpenstackPort for {}", getPortName(port));
Hyunsun Moon8539b042015-11-07 22:08:43 -0800237 return;
238 }
239
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800240 MacAddress mac = vPort.macAddress();
241 HostId hostId = HostId.hostId(mac);
Hyunsun Moon8539b042015-11-07 22:08:43 -0800242
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800243 Host host = hostService.getHost(hostId);
244 if (host != null) {
245 // Host is already known to the system, no HOST_ADDED event is triggered in this case.
246 // It happens when the application is restarted.
247 // TODO check host description if it has all the information
248 serviceVmAdded(host);
Hyunsun Moon8539b042015-11-07 22:08:43 -0800249 return;
250 }
251
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800252 Set<IpAddress> ip = Sets.newHashSet(vPort.fixedIps().values());
253 SparseAnnotations annotations = DefaultAnnotations.builder()
254 .set(OPENSTACK_VM_ID, vPort.deviceId())
255 .set(SERVICE_ID, vPort.networkId())
256 .set(LOCATION_IP, node.localIp().toString())
257 .build();
258
259 HostDescription hostDesc = new DefaultHostDescription(
260 mac,
261 VlanId.NONE,
262 new HostLocation(connectPoint, System.currentTimeMillis()),
263 ip,
264 annotations);
265
266 hostProvider.hostDetected(hostId, hostDesc, false);
Hyunsun Moon8539b042015-11-07 22:08:43 -0800267 }
268
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800269 @Override
270 public void removeServiceVm(ConnectPoint connectPoint) {
271 Host host = hostService.getConnectedHosts(connectPoint)
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800272 .stream()
273 .findFirst()
274 .orElse(null);
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800275
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800276 if (host == null) {
277 log.debug("No host is connected on {}", connectPoint.toString());
278 return;
279 }
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800280
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800281 hostProvider.hostVanished(host.id());
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800282 }
283
284 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800285 * Returns CordService by service ID.
Hyunsun Moonbfc47d12015-12-07 14:06:28 -0800286 *
287 * @param serviceId service id
288 * @return cord service, or null if it fails to get network from OpenStack
289 */
290 private CordService getCordService(CordServiceId serviceId) {
291 OpenstackNetwork vNet = openstackService.network(serviceId.id());
292 if (vNet == null) {
293 log.warn("Couldn't find OpenStack network for service {}", serviceId.id());
294 return null;
295 }
296
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800297 OpenstackSubnet subnet = vNet.subnets().stream()
298 .findFirst()
299 .orElse(null);
300 if (subnet == null) {
301 log.warn("Couldn't find OpenStack subnet for service {}", serviceId.id());
302 return null;
303 }
304
305 Set<CordServiceId> tServices = Sets.newHashSet();
306 // TODO get tenant services from XOS
307
308 Map<Host, IpAddress> hosts = getHostsWithOpenstackNetwork(vNet)
309 .stream()
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800310 .collect(Collectors.toMap(host -> host, this::getTunnelIp));
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800311
312 return new CordService(vNet, subnet, hosts, tServices);
Hyunsun Moonbfc47d12015-12-07 14:06:28 -0800313 }
314
315 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800316 * Returns CordService by OpenStack network.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800317 *
318 * @param vNet OpenStack network
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800319 * @return cord service
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800320 */
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800321 private CordService getCordService(OpenstackNetwork vNet) {
322 checkNotNull(vNet);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800323
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800324 CordServiceId serviceId = CordServiceId.of(vNet.id());
325 OpenstackSubnet subnet = vNet.subnets().stream()
326 .findFirst()
327 .orElse(null);
328 if (subnet == null) {
329 log.warn("Couldn't find OpenStack subnet for service {}", serviceId);
330 return null;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800331 }
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800332
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800333 Set<CordServiceId> tServices = Sets.newHashSet();
334 // TODO get tenant services from XOS
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800335
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800336 Map<Host, IpAddress> hosts = getHostsWithOpenstackNetwork(vNet)
337 .stream()
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800338 .collect(Collectors.toMap(host -> host, this::getTunnelIp));
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800339
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800340 return new CordService(vNet, subnet, hosts, tServices);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800341 }
342
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800343 /**
344 * Returns IP address for tunneling for a given host.
345 *
346 * @param host host
347 * @return ip address
348 */
349 private IpAddress getTunnelIp(Host host) {
350 return IpAddress.valueOf(host.annotations().value(LOCATION_IP));
351 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700352
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800353 /**
354 * Returns port name.
355 *
356 * @param port port
357 * @return port name
358 */
359 private String getPortName(Port port) {
360 return port.annotations().value("portName");
361 }
Hyunsun Moon8539b042015-11-07 22:08:43 -0800362
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800363 /**
364 * Returns hosts associated with a given OpenStack network.
365 *
366 * @param vNet openstack network
367 * @return set of hosts
368 */
369 private Set<Host> getHostsWithOpenstackNetwork(OpenstackNetwork vNet) {
370 checkNotNull(vNet);
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700371
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800372 Set<Host> hosts = openstackService.ports(vNet.id()).stream()
373 .filter(port -> port.deviceOwner().contains("compute"))
374 .map(port -> hostService.getHostsByMac(port.macAddress())
375 .stream()
376 .findFirst()
377 .orElse(null))
378 .collect(Collectors.toSet());
379
380 hosts.remove(null);
381 return hosts;
382 }
383
384 /**
385 * Handles VM detected situation.
386 *
387 * @param host host
388 */
389 private void serviceVmAdded(Host host) {
390 String vNetId = host.annotations().value(SERVICE_ID);
391 OpenstackNetwork vNet = openstackService.network(vNetId);
392 if (vNet == null) {
393 log.warn("Failed to get OpenStack network {} for VM {}({}).",
394 vNetId,
395 host.id(),
396 host.annotations().value(OPENSTACK_VM_ID));
397 return;
398 }
399
400 log.info("VM {} is detected, MAC: {} IP: {}",
401 host.annotations().value(OPENSTACK_VM_ID),
402 host.mac(),
403 host.ipAddresses().stream().findFirst().get());
404
405 CordService service = getCordService(vNet);
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800406 if (service == null) {
407 return;
408 }
409
410 if (service.serviceType().equals(CordService.ServiceType.MANAGEMENT)) {
411 ruleInstaller.populateManagementNetworkRules(host, service);
412 } else {
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800413 // TODO check if the service needs an update on its group buckets after done CORD-433
414 ruleInstaller.updateServiceGroup(service);
415 arpProxy.addServiceIp(service.serviceIp());
Hyunsun Moon746956f2016-01-24 21:47:06 -0800416
417 // sends gratuitous ARP here for the case of adding existing VMs
418 // when ONOS or cordvtn app is restarted
419 arpProxy.sendGratuitousArp(service.serviceIp(), gatewayMac, Sets.newHashSet(host));
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800420 }
421
422 ruleInstaller.populateBasicConnectionRules(host, getTunnelIp(host), vNet);
423 }
424
425 /**
426 * Handles VM removed situation.
427 *
428 * @param host host
429 */
430 private void serviceVmRemoved(Host host) {
431 String vNetId = host.annotations().value(SERVICE_ID);
432 OpenstackNetwork vNet = openstackService.network(host.annotations().value(SERVICE_ID));
433 if (vNet == null) {
434 log.warn("Failed to get OpenStack network {} for VM {}({}).",
435 vNetId,
436 host.id(),
437 host.annotations().value(OPENSTACK_VM_ID));
438 return;
439 }
440
441 log.info("VM {} is vanished, MAC: {} IP: {}",
442 host.annotations().value(OPENSTACK_VM_ID),
443 host.mac(),
444 host.ipAddresses().stream().findFirst().get());
445
446 ruleInstaller.removeBasicConnectionRules(host);
447
448 CordService service = getCordService(vNet);
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800449 if (service == null) {
450 return;
451 }
452
453 if (service.serviceType().equals(CordService.ServiceType.MANAGEMENT)) {
454 ruleInstaller.removeManagementNetworkRules(host, service);
455 } else {
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800456 // TODO check if the service needs an update on its group buckets after done CORD-433
457 ruleInstaller.updateServiceGroup(service);
458
459 if (getHostsWithOpenstackNetwork(vNet).isEmpty()) {
460 arpProxy.removeServiceIp(service.serviceIp());
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700461 }
462 }
463 }
464
Hyunsun Moon746956f2016-01-24 21:47:06 -0800465 /**
466 * Sets service network gateway MAC address and sends out gratuitous ARP to all
467 * VMs to update the gateway MAC address.
468 *
469 * @param mac mac address
470 */
471 private void setServiceGatewayMac(MacAddress mac) {
472 if (mac != null && !mac.equals(gatewayMac)) {
473 gatewayMac = mac;
474 log.debug("Set service gateway MAC address to {}", gatewayMac.toString());
475 }
476
477 // TODO get existing service list from XOS and replace the loop below
478 Set<String> vNets = Sets.newHashSet();
479 hostService.getHosts().forEach(host -> vNets.add(host.annotations().value(SERVICE_ID)));
480 vNets.remove(null);
481
482 vNets.stream().forEach(vNet -> {
483 CordService service = getCordService(CordServiceId.of(vNet));
484 if (service != null) {
485 arpProxy.sendGratuitousArp(
486 service.serviceIp(),
487 gatewayMac,
488 service.hosts().keySet());
489 }
490 });
491 }
492
493 /**
494 * Updates configurations.
495 */
496 private void readConfiguration() {
497 CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class);
498 if (config == null) {
499 log.debug("No configuration found");
500 return;
501 }
502
503 setServiceGatewayMac(config.gatewayMac());
504 }
505
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700506 private class InternalHostListener implements HostListener {
507
508 @Override
509 public void event(HostEvent event) {
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800510 Host host = event.subject();
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700511
512 switch (event.type()) {
513 case HOST_ADDED:
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800514 eventExecutor.submit(() -> serviceVmAdded(host));
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700515 break;
516 case HOST_REMOVED:
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800517 eventExecutor.submit(() -> serviceVmRemoved(host));
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700518 break;
519 default:
520 break;
521 }
522 }
523 }
524
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800525 private class InternalPacketProcessor implements PacketProcessor {
526
527 @Override
528 public void process(PacketContext context) {
529 if (context.isHandled()) {
530 return;
531 }
532
533 Ethernet ethPacket = context.inPacket().parsed();
Hyunsun Moon746956f2016-01-24 21:47:06 -0800534 if (ethPacket == null || ethPacket.getEtherType() != Ethernet.TYPE_ARP) {
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800535 return;
536 }
537
Hyunsun Moon746956f2016-01-24 21:47:06 -0800538 arpProxy.processArpPacket(context, ethPacket, gatewayMac);
539 }
540 }
541
542 private class InternalConfigListener implements NetworkConfigListener {
543
544 @Override
545 public void event(NetworkConfigEvent event) {
546 if (!event.configClass().equals(CordVtnConfig.class)) {
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800547 return;
548 }
549
Hyunsun Moon746956f2016-01-24 21:47:06 -0800550 switch (event.type()) {
551 case CONFIG_ADDED:
552 case CONFIG_UPDATED:
553 log.info("Network configuration changed");
554 eventExecutor.execute(CordVtn.this::readConfiguration);
555 break;
556 default:
557 break;
558 }
Hyunsun Moon42c7b4e2016-01-11 15:30:42 -0800559 }
560 }
Hyunsun Moond0e932a2015-09-15 22:39:16 -0700561}