blob: 2e38251ee7354ce31b1da35f86620abdc8bd6a60 [file] [log] [blame]
lishuai6c56f5e2015-11-17 16:38:19 +08001/*
2 * Copyright 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.vtn.manager.impl;
17
jiangruic69a7fd2015-11-19 15:40:01 +080018import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST;
lishuai6c56f5e2015-11-17 16:38:19 +080019import static org.slf4j.LoggerFactory.getLogger;
20
21import java.util.Collection;
22import java.util.HashMap;
23import java.util.HashSet;
24import java.util.Iterator;
jiangruic69a7fd2015-11-19 15:40:01 +080025import java.util.List;
lishuai6c56f5e2015-11-17 16:38:19 +080026import java.util.Map;
27import java.util.Set;
28
29import org.apache.felix.scr.annotations.Activate;
30import org.apache.felix.scr.annotations.Component;
31import org.apache.felix.scr.annotations.Deactivate;
32import org.apache.felix.scr.annotations.Reference;
33import org.apache.felix.scr.annotations.ReferenceCardinality;
34import org.apache.felix.scr.annotations.Service;
jiangruic69a7fd2015-11-19 15:40:01 +080035import org.onlab.packet.Ip4Address;
lishuai6c56f5e2015-11-17 16:38:19 +080036import org.onlab.packet.IpAddress;
37import org.onlab.packet.MacAddress;
38import org.onlab.util.KryoNamespace;
39import org.onosproject.core.ApplicationId;
40import org.onosproject.core.CoreService;
41import org.onosproject.mastership.MastershipService;
42import org.onosproject.net.Device;
43import org.onosproject.net.DeviceId;
44import org.onosproject.net.Host;
45import org.onosproject.net.Port;
46import org.onosproject.net.PortNumber;
47import org.onosproject.net.behaviour.BridgeConfig;
48import org.onosproject.net.behaviour.BridgeDescription;
jiangruic69a7fd2015-11-19 15:40:01 +080049import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
lishuai6c56f5e2015-11-17 16:38:19 +080050import org.onosproject.net.config.NetworkConfigService;
51import org.onosproject.net.config.basics.BasicDeviceConfig;
52import org.onosproject.net.device.DeviceEvent;
53import org.onosproject.net.device.DeviceListener;
54import org.onosproject.net.device.DeviceService;
55import org.onosproject.net.driver.DriverHandler;
56import org.onosproject.net.driver.DriverService;
jiangruic69a7fd2015-11-19 15:40:01 +080057import org.onosproject.net.flow.DefaultTrafficTreatment;
58import org.onosproject.net.flow.TrafficTreatment.Builder;
59import org.onosproject.net.flow.instructions.ExtensionTreatment;
lishuai6c56f5e2015-11-17 16:38:19 +080060import org.onosproject.net.flowobjective.Objective;
jiangruic69a7fd2015-11-19 15:40:01 +080061import org.onosproject.net.group.DefaultGroupBucket;
62import org.onosproject.net.group.DefaultGroupDescription;
63import org.onosproject.net.group.DefaultGroupKey;
64import org.onosproject.net.group.GroupBucket;
65import org.onosproject.net.group.GroupBuckets;
66import org.onosproject.net.group.GroupDescription;
67import org.onosproject.net.group.GroupKey;
68import org.onosproject.net.group.GroupService;
lishuai6c56f5e2015-11-17 16:38:19 +080069import org.onosproject.net.host.HostEvent;
70import org.onosproject.net.host.HostListener;
71import org.onosproject.net.host.HostService;
72import org.onosproject.store.serializers.KryoNamespaces;
lishuai6c56f5e2015-11-17 16:38:19 +080073import org.onosproject.store.service.EventuallyConsistentMap;
74import org.onosproject.store.service.LogicalClockService;
lishuai6c56f5e2015-11-17 16:38:19 +080075import org.onosproject.store.service.StorageService;
76import org.onosproject.vtn.manager.VTNService;
77import org.onosproject.vtn.table.ClassifierService;
78import org.onosproject.vtn.table.L2ForwardService;
79import org.onosproject.vtn.table.impl.ClassifierServiceImpl;
80import org.onosproject.vtn.table.impl.L2ForwardServiceImpl;
81import org.onosproject.vtn.util.DataPathIdGenerator;
82import org.onosproject.vtn.util.VtnConfig;
83import org.onosproject.vtn.util.VtnData;
84import org.onosproject.vtnrsc.SegmentationId;
85import org.onosproject.vtnrsc.SubnetId;
86import org.onosproject.vtnrsc.TenantId;
87import org.onosproject.vtnrsc.TenantNetwork;
88import org.onosproject.vtnrsc.TenantNetworkId;
89import org.onosproject.vtnrsc.VirtualPort;
90import org.onosproject.vtnrsc.VirtualPortId;
91import org.onosproject.vtnrsc.tenantnetwork.TenantNetworkService;
92import org.onosproject.vtnrsc.virtualport.VirtualPortService;
93import org.slf4j.Logger;
94
jiangruic69a7fd2015-11-19 15:40:01 +080095import com.google.common.collect.Lists;
lishuai6c56f5e2015-11-17 16:38:19 +080096import com.google.common.collect.Sets;
97
98/**
99 * Provides implementation of VTNService.
100 */
101@Component(immediate = true)
102@Service
103public class VTNManager implements VTNService {
104 private final Logger log = getLogger(getClass());
105 private static final String APP_ID = "org.onosproject.app.vtn";
106
107 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
108 protected NetworkConfigService configService;
109
110 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
111 protected DeviceService deviceService;
112
113 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
114 protected HostService hostService;
115
116 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
117 protected CoreService coreService;
118
119 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
120 protected StorageService storageService;
121
122 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
123 protected TenantNetworkService tenantNetworkService;
124
125 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
126 protected VirtualPortService virtualPortService;
127
128 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
129 protected DriverService driverService;
130
131 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
132 protected LogicalClockService clockService;
133
134 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
135 protected MastershipService mastershipService;
136
jiangruic69a7fd2015-11-19 15:40:01 +0800137 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
138 protected GroupService groupService;
139
lishuai6c56f5e2015-11-17 16:38:19 +0800140 private ApplicationId appId;
141 private ClassifierService classifierService;
142 private L2ForwardService l2ForwardService;
143
144 private final HostListener hostListener = new InnerHostListener();
145 private final DeviceListener deviceListener = new InnerDeviceListener();
146
147 private static final String IFACEID = "ifaceid";
148 private static final String CONTROLLER_IP_KEY = "ipaddress";
149 public static final String DRIVER_NAME = "onosfw";
150 private static final String EX_PORT_NAME = "eth0";
151 private static final String SWITCHES_OF_CONTROLLER = "switchesOfController";
152 private static final String SWITCH_OF_LOCAL_HOST_PORTS = "switchOfLocalHostPorts";
jiangruic69a7fd2015-11-19 15:40:01 +0800153 private static final String DEFAULT_IP = "0.0.0.0";
lishuai6c56f5e2015-11-17 16:38:19 +0800154
155 private EventuallyConsistentMap<IpAddress, Boolean> switchesOfController;
jiangruic69a7fd2015-11-19 15:40:01 +0800156 private EventuallyConsistentMap<DeviceId, NetworkOfLocalHostPorts> switchOfLocalHostPorts;
lishuai6c56f5e2015-11-17 16:38:19 +0800157
158 @Activate
159 public void activate() {
160 appId = coreService.registerApplication(APP_ID);
161 classifierService = new ClassifierServiceImpl(appId);
162 l2ForwardService = new L2ForwardServiceImpl(appId);
163
164 deviceService.addListener(deviceListener);
165 hostService.addListener(hostListener);
166
167 KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
168 .register(KryoNamespaces.API)
169 .register(NetworkOfLocalHostPorts.class)
170 .register(TenantNetworkId.class)
171 .register(Host.class)
172 .register(TenantNetwork.class)
173 .register(TenantId.class)
174 .register(SubnetId.class);
175
176 switchesOfController = storageService
177 .<IpAddress, Boolean>eventuallyConsistentMapBuilder()
178 .withName(SWITCHES_OF_CONTROLLER).withSerializer(serializer)
179 .withTimestampProvider((k, v) -> clockService.getTimestamp())
180 .build();
181
182 switchOfLocalHostPorts = storageService
jiangruic69a7fd2015-11-19 15:40:01 +0800183 .<DeviceId, NetworkOfLocalHostPorts>eventuallyConsistentMapBuilder()
184 .withName(SWITCH_OF_LOCAL_HOST_PORTS).withSerializer(serializer)
185 .withTimestampProvider((k, v) -> clockService.getTimestamp())
lishuai6c56f5e2015-11-17 16:38:19 +0800186 .build();
187
188 log.info("Started");
189 }
190
191 @Deactivate
192 public void deactivate() {
193 deviceService.removeListener(deviceListener);
194 hostService.removeListener(hostListener);
195 log.info("Stopped");
196 }
197
198 @Override
199 public void onControllerDetected(Device controllerDevice) {
200 if (controllerDevice == null) {
201 log.error("The controller device is null");
202 return;
203 }
204 String localIpAddress = controllerDevice.annotations()
205 .value(CONTROLLER_IP_KEY);
206 IpAddress localIp = IpAddress.valueOf(localIpAddress);
207 DeviceId controllerDeviceId = controllerDevice.id();
208 DriverHandler handler = driverService.createHandler(controllerDeviceId);
209 if (mastershipService.isLocalMaster(controllerDeviceId)) {
210 // Get DataPathIdGenerator
211 String ipaddress = controllerDevice.annotations().value("ipaddress");
212 DataPathIdGenerator dpidGenerator = DataPathIdGenerator.builder()
213 .addIpAddress(ipaddress).build();
214 DeviceId deviceId = dpidGenerator.getDeviceId();
215 String dpid = dpidGenerator.getDpId();
216 // Inject pipeline driver name
217 BasicDeviceConfig config = configService.addConfig(deviceId,
218 BasicDeviceConfig.class);
219 config.driver(DRIVER_NAME);
220 configService.applyConfig(deviceId, BasicDeviceConfig.class, config.node());
221 // Add Bridge
222 VtnConfig.applyBridgeConfig(handler, dpid, EX_PORT_NAME);
223 log.info("A new ovs is created in node {}", localIp.toString());
224 switchesOfController.put(localIp, true);
225 }
226 // Create tunnel in br-int on all controllers
227 programTunnelConfig(controllerDeviceId, localIp, handler);
228 }
229
230 @Override
231 public void onControllerVanished(Device controllerDevice) {
232 if (controllerDevice == null) {
233 log.error("The device is null");
234 return;
235 }
236 String dstIp = controllerDevice.annotations().value(CONTROLLER_IP_KEY);
237 IpAddress dstIpAddress = IpAddress.valueOf(dstIp);
238 DeviceId controllerDeviceId = controllerDevice.id();
239 if (mastershipService.isLocalMaster(controllerDeviceId)) {
240 switchesOfController.remove(dstIpAddress);
241 }
242 // remove tunnel in br-int on other controllers
243 programTunnelConfig(controllerDeviceId, dstIpAddress, null);
244 }
245
246 @Override
247 public void onOvsDetected(Device device) {
248 // Create tunnel out flow rules
249 applyTunnelOut(device, Objective.Operation.ADD);
250 }
251
252 @Override
253 public void onOvsVanished(Device device) {
254 // Remove Tunnel out flow rules
255 applyTunnelOut(device, Objective.Operation.REMOVE);
256 }
257
258 @Override
259 public void onHostDetected(Host host) {
260 // apply L2 openflow rules
261 applyHostMonitoredL2Rules(host, Objective.Operation.ADD);
262 }
263
264 @Override
265 public void onHostVanished(Host host) {
266 // apply L2 openflow rules
267 applyHostMonitoredL2Rules(host, Objective.Operation.REMOVE);
268 }
269
270 private void programTunnelConfig(DeviceId localDeviceId, IpAddress localIp,
271 DriverHandler localHandler) {
jiangruic69a7fd2015-11-19 15:40:01 +0800272 if (mastershipService.isLocalMaster(localDeviceId)) {
273 VtnConfig.applyTunnelConfig(localHandler, localIp, IpAddress.valueOf(DEFAULT_IP));
274 log.info("Add tunnel on {}", localIp);
275 }
lishuai6c56f5e2015-11-17 16:38:19 +0800276 }
277
278 private void applyTunnelOut(Device device, Objective.Operation type) {
279 if (device == null) {
280 log.error("The device is null");
281 return;
282 }
283 if (!mastershipService.isLocalMaster(device.id())) {
284 return;
285 }
286 String controllerIp = VtnData.getControllerIpOfSwitch(device);
287 if (controllerIp == null) {
288 log.error("Can't find controller of device: {}",
289 device.id().toString());
290 return;
291 }
292 IpAddress ipAddress = IpAddress.valueOf(controllerIp);
293 if (!switchesOfController.containsKey(ipAddress)) {
294 log.error("Can't find controller of device: {}",
295 device.id().toString());
296 return;
297 }
298 if (type == Objective.Operation.ADD) {
299 switchOfLocalHostPorts.put(device.id(), new NetworkOfLocalHostPorts());
300 } else if (type == Objective.Operation.REMOVE) {
301 switchOfLocalHostPorts.remove(device.id());
302 }
303 Iterable<Device> devices = deviceService.getAvailableDevices();
304 DeviceId localControllerId = VtnData.getControllerId(device, devices);
305 DriverHandler handler = driverService.createHandler(localControllerId);
306 Set<PortNumber> ports = VtnConfig.getPortNumbers(handler);
307 Iterable<Host> allHosts = hostService.getHosts();
jiangruic69a7fd2015-11-19 15:40:01 +0800308 String tunnelName = "vxlan-" + DEFAULT_IP;
lishuai6c56f5e2015-11-17 16:38:19 +0800309 if (allHosts != null) {
310 Sets.newHashSet(allHosts).stream().forEach(host -> {
311 MacAddress hostMac = host.mac();
312 String ifaceId = host.annotations().value(IFACEID);
313 if (ifaceId == null) {
314 log.error("The ifaceId of Host is null");
315 return;
316 }
317 VirtualPortId virtualPortId = VirtualPortId.portId(ifaceId);
318 VirtualPort virtualPort = virtualPortService
319 .getPort(virtualPortId);
320 TenantNetwork network = tenantNetworkService
321 .getNetwork(virtualPort.networkId());
322 SegmentationId segmentationId = network.segmentationId();
323 DeviceId remoteDeviceId = host.location().deviceId();
324 Device remoteDevice = deviceService.getDevice(remoteDeviceId);
325 String remoteControllerIp = VtnData
326 .getControllerIpOfSwitch(remoteDevice);
327 if (remoteControllerIp == null) {
328 log.error("Can't find remote controller of device: {}",
329 remoteDeviceId.toString());
330 return;
331 }
332 IpAddress remoteIpAddress = IpAddress
333 .valueOf(remoteControllerIp);
lishuai6c56f5e2015-11-17 16:38:19 +0800334 ports.stream()
335 .filter(p -> p.name().equalsIgnoreCase(tunnelName))
336 .forEach(p -> {
337 l2ForwardService
338 .programTunnelOut(device.id(), segmentationId, p,
jiangruic69a7fd2015-11-19 15:40:01 +0800339 hostMac, type, remoteIpAddress);
lishuai6c56f5e2015-11-17 16:38:19 +0800340 });
341 });
342 }
343 }
344
345 private void applyHostMonitoredL2Rules(Host host, Objective.Operation type) {
346 DeviceId deviceId = host.location().deviceId();
347 if (!mastershipService.isLocalMaster(deviceId)) {
348 return;
349 }
350 String ifaceId = host.annotations().value(IFACEID);
351 if (ifaceId == null) {
352 log.error("The ifaceId of Host is null");
353 return;
354 }
355 VirtualPortId virtualPortId = VirtualPortId.portId(ifaceId);
356 VirtualPort virtualPort = virtualPortService.getPort(virtualPortId);
357 if (virtualPort == null) {
358 log.error("The virtualPort of host is null");
359 return;
360 }
361
362 Iterable<Device> devices = deviceService.getAvailableDevices();
363 PortNumber inPort = host.location().port();
364 MacAddress mac = host.mac();
365 Device device = deviceService.getDevice(deviceId);
366 String controllerIp = VtnData.getControllerIpOfSwitch(device);
367 IpAddress ipAddress = IpAddress.valueOf(controllerIp);
368 TenantNetwork network = tenantNetworkService.getNetwork(virtualPort.networkId());
369 if (network == null) {
370 log.error("Can't find network of the host");
371 return;
372 }
373 SegmentationId segmentationId = network.segmentationId();
374 // Get all the tunnel PortNumber in the current node
375 Iterable<Port> ports = deviceService.getPorts(deviceId);
376 Collection<PortNumber> localTunnelPorts = VtnData.getLocalTunnelPorts(ports);
377 // Get all the local vm's PortNumber in the current node
378 Map<TenantNetworkId, Set<PortNumber>> localHostPorts = switchOfLocalHostPorts
jiangruic69a7fd2015-11-19 15:40:01 +0800379 .get(deviceId).getNetworkOfLocalHostPorts();
lishuai6c56f5e2015-11-17 16:38:19 +0800380 Set<PortNumber> networkOflocalHostPorts = localHostPorts.get(network.id());
jiangruic69a7fd2015-11-19 15:40:01 +0800381 for (PortNumber p : localTunnelPorts) {
382 programGroupTable(deviceId, appId, p, devices, type);
383 }
lishuai6c56f5e2015-11-17 16:38:19 +0800384
385 if (type == Objective.Operation.ADD) {
386 if (networkOflocalHostPorts == null) {
387 networkOflocalHostPorts = new HashSet<PortNumber>();
388 localHostPorts.putIfAbsent(network.id(), networkOflocalHostPorts);
389 }
390 networkOflocalHostPorts.add(inPort);
jiangruic69a7fd2015-11-19 15:40:01 +0800391 l2ForwardService.programLocalBcastRules(deviceId, segmentationId,
392 inPort, networkOflocalHostPorts,
393 localTunnelPorts,
394 type);
lishuai6c56f5e2015-11-17 16:38:19 +0800395 classifierService.programTunnelIn(deviceId, segmentationId,
396 localTunnelPorts,
397 type);
398 } else if (type == Objective.Operation.REMOVE) {
jiangruic69a7fd2015-11-19 15:40:01 +0800399 if (networkOflocalHostPorts != null) {
400 l2ForwardService.programLocalBcastRules(deviceId, segmentationId,
401 inPort, networkOflocalHostPorts,
402 localTunnelPorts,
403 type);
404 networkOflocalHostPorts.remove(inPort);
405 if (networkOflocalHostPorts.isEmpty()) {
406 classifierService.programTunnelIn(deviceId, segmentationId,
407 localTunnelPorts,
408 type);
409 switchOfLocalHostPorts.get(deviceId).getNetworkOfLocalHostPorts()
410 .remove(virtualPort.networkId());
411 }
lishuai6c56f5e2015-11-17 16:38:19 +0800412 }
413 }
414
jiangruic69a7fd2015-11-19 15:40:01 +0800415 l2ForwardService.programLocalOut(deviceId, segmentationId, inPort, mac,
416 type);
417
lishuai6c56f5e2015-11-17 16:38:19 +0800418 l2ForwardService.programTunnelBcastRules(deviceId, segmentationId,
419 networkOflocalHostPorts,
420 localTunnelPorts,
421 type);
422
423 programTunnelOuts(devices, ipAddress, segmentationId, mac,
424 type);
425
426 classifierService.programLocalIn(deviceId, segmentationId, inPort, mac,
427 appId, type);
428 }
429
430 private void programTunnelOuts(Iterable<Device> devices,
431 IpAddress ipAddress,
432 SegmentationId segmentationId,
433 MacAddress dstMac,
434 Objective.Operation type) {
jiangruic69a7fd2015-11-19 15:40:01 +0800435 String tunnelName = "vxlan-" + DEFAULT_IP;
lishuai6c56f5e2015-11-17 16:38:19 +0800436 Sets.newHashSet(devices).stream()
jiangruic69a7fd2015-11-19 15:40:01 +0800437 .filter(d -> d.type() == Device.Type.CONTROLLER)
438 .filter(d -> !("ovsdb:" + ipAddress).equals(d.id().toString()))
439 .forEach(d -> {
lishuai6c56f5e2015-11-17 16:38:19 +0800440 DriverHandler handler = driverService.createHandler(d.id());
441 BridgeConfig bridgeConfig = handler
442 .behaviour(BridgeConfig.class);
443 Collection<BridgeDescription> bridgeDescriptions = bridgeConfig
444 .getBridges();
445 Set<PortNumber> ports = bridgeConfig.getPortNumbers();
446 Iterator<BridgeDescription> it = bridgeDescriptions
447 .iterator();
448 if (it.hasNext()) {
449 BridgeDescription sw = it.next();
450 ports.stream()
451 .filter(p -> p.name()
452 .equalsIgnoreCase(tunnelName))
453 .forEach(p -> {
454 l2ForwardService.programTunnelOut(sw.deviceId(),
455 segmentationId, p,
jiangruic69a7fd2015-11-19 15:40:01 +0800456 dstMac, type, ipAddress);
lishuai6c56f5e2015-11-17 16:38:19 +0800457 });
458 }
459 });
460 }
461
462 private class InnerDeviceListener implements DeviceListener {
463
464 @Override
465 public void event(DeviceEvent event) {
466 Device device = event.subject();
467 if (Device.Type.CONTROLLER == device.type()) {
468 if (DeviceEvent.Type.DEVICE_ADDED == event.type()) {
469 onControllerDetected(device);
470 }
471 if (DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED == event.type()) {
472 if (deviceService.isAvailable(device.id())) {
473 onControllerDetected(device);
474 } else {
475 onControllerVanished(device);
476 }
477 }
478 } else if (Device.Type.SWITCH == device.type()) {
479 if (DeviceEvent.Type.DEVICE_ADDED == event.type()) {
480 onOvsDetected(device);
481 }
482 if (DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED == event.type()) {
483 if (deviceService.isAvailable(device.id())) {
484 onOvsDetected(device);
485 } else {
486 onOvsVanished(device);
487 }
488 }
489 } else {
490 log.info("Do nothing for this device type");
491 }
492 }
493 }
494
495 private class InnerHostListener implements HostListener {
496
497 @Override
498 public void event(HostEvent event) {
499 Host host = event.subject();
500 if (HostEvent.Type.HOST_ADDED == event.type()) {
501 onHostDetected(host);
502 } else if (HostEvent.Type.HOST_REMOVED == event.type()) {
503 onHostVanished(host);
504 } else if (HostEvent.Type.HOST_UPDATED == event.type()) {
505 onHostVanished(host);
506 onHostDetected(host);
507 }
508 }
509
510 }
511
512 // Local Host Ports of Network.
513 private class NetworkOfLocalHostPorts {
514 private final Map<TenantNetworkId, Set<PortNumber>> networkOfLocalHostPorts =
515 new HashMap<TenantNetworkId, Set<PortNumber>>();
516
517 public Map<TenantNetworkId, Set<PortNumber>> getNetworkOfLocalHostPorts() {
518 return networkOfLocalHostPorts;
519 }
520 }
521
jiangruic69a7fd2015-11-19 15:40:01 +0800522 private void programGroupTable(DeviceId deviceId, ApplicationId appid,
523 PortNumber portNumber, Iterable<Device> devices, Objective.Operation type) {
524 if (type.equals(Objective.Operation.REMOVE)) {
525 return;
526 }
527
528 List<GroupBucket> buckets = Lists.newArrayList();
529 Sets.newHashSet(devices)
530 .stream()
531 .filter(d -> d.type() == Device.Type.CONTROLLER)
532 .filter(d -> !deviceId.equals(d.id()))
533 .forEach(d -> {
534 String ipAddress = d.annotations()
535 .value(CONTROLLER_IP_KEY);
536 Ip4Address dst = Ip4Address.valueOf(ipAddress);
537 Builder builder = DefaultTrafficTreatment.builder();
538
539 DriverHandler handler = driverService.createHandler(deviceId);
540 ExtensionTreatmentResolver resolver = handler.behaviour(ExtensionTreatmentResolver.class);
541 ExtensionTreatment treatment = resolver.getExtensionInstruction(NICIRA_SET_TUNNEL_DST.type());
542 try {
543 treatment.setPropertyValue("tunnelDst", dst);
544 } catch (Exception e) {
545 log.error("Failed to get extension instruction to set tunnel dst {}", deviceId);
546 }
547
548 builder.extension(treatment, deviceId);
549 builder.setOutput(portNumber);
550 GroupBucket bucket = DefaultGroupBucket
551 .createAllGroupBucket(builder.build());
552 buckets.add(bucket);
553 });
554 final GroupKey key = new DefaultGroupKey(APP_ID.getBytes());
555 GroupDescription groupDescription = new DefaultGroupDescription(deviceId,
556 GroupDescription.Type.ALL,
557 new GroupBuckets(buckets),
558 key,
559 L2ForwardServiceImpl.GROUP_ID,
560 appid);
561 groupService.addGroup(groupDescription);
562 }
lishuai6c56f5e2015-11-17 16:38:19 +0800563}