blob: f7d2886cfc780c421b3e88a83adb60987fda0b93 [file] [log] [blame]
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -07001/*
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.impl;
17
18import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
19import static org.onlab.util.Tools.groupedThreads;
20import static org.slf4j.LoggerFactory.getLogger;
21
22import java.util.ArrayList;
23import java.util.Collection;
24import java.util.HashSet;
25import java.util.Iterator;
26import java.util.List;
27import java.util.Set;
28import java.util.concurrent.ScheduledExecutorService;
29
30import org.apache.felix.scr.annotations.Activate;
31import org.apache.felix.scr.annotations.Component;
32import org.apache.felix.scr.annotations.Deactivate;
33import org.apache.felix.scr.annotations.Reference;
34import org.apache.felix.scr.annotations.ReferenceCardinality;
35import org.apache.felix.scr.annotations.Service;
CNluciusa66c3972015-09-06 20:31:29 +080036import org.onlab.osgi.DefaultServiceDirectory;
37import org.onlab.osgi.ServiceDirectory;
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -070038import org.onlab.packet.IpAddress;
39import org.onlab.packet.MacAddress;
40import org.onlab.util.KryoNamespace;
41import org.onosproject.core.ApplicationId;
42import org.onosproject.core.CoreService;
43import org.onosproject.net.Device;
44import org.onosproject.net.DeviceId;
45import org.onosproject.net.Host;
46import org.onosproject.net.HostId;
47import org.onosproject.net.Port;
48import org.onosproject.net.PortNumber;
49import org.onosproject.net.behaviour.BridgeConfig;
50import org.onosproject.net.behaviour.BridgeDescription;
51import org.onosproject.net.behaviour.BridgeName;
52import org.onosproject.net.behaviour.DefaultTunnelDescription;
53import org.onosproject.net.behaviour.IpTunnelEndPoint;
CNluciusa66c3972015-09-06 20:31:29 +080054import org.onosproject.net.behaviour.Pipeliner;
55import org.onosproject.net.behaviour.PipelinerContext;
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -070056import org.onosproject.net.behaviour.TunnelConfig;
57import org.onosproject.net.behaviour.TunnelDescription;
58import org.onosproject.net.behaviour.TunnelEndPoint;
59import org.onosproject.net.device.DeviceEvent;
60import org.onosproject.net.device.DeviceListener;
61import org.onosproject.net.device.DeviceService;
CNluciusa66c3972015-09-06 20:31:29 +080062import org.onosproject.net.driver.DefaultDriverData;
63import org.onosproject.net.driver.Driver;
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -070064import org.onosproject.net.driver.DriverHandler;
65import org.onosproject.net.driver.DriverService;
66import org.onosproject.net.flow.DefaultTrafficSelector;
67import org.onosproject.net.flow.DefaultTrafficTreatment;
68import org.onosproject.net.flow.FlowRuleService;
69import org.onosproject.net.flow.TrafficSelector;
70import org.onosproject.net.flow.TrafficTreatment;
71import org.onosproject.net.flow.criteria.Criteria;
72import org.onosproject.net.flow.instructions.Instructions;
73import org.onosproject.net.flowobjective.DefaultForwardingObjective;
74import org.onosproject.net.flowobjective.FlowObjectiveService;
CNluciusa66c3972015-09-06 20:31:29 +080075import org.onosproject.net.flowobjective.FlowObjectiveStore;
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -070076import org.onosproject.net.flowobjective.ForwardingObjective;
77import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
78import org.onosproject.net.flowobjective.Objective;
79import org.onosproject.net.host.HostEvent;
80import org.onosproject.net.host.HostListener;
81import org.onosproject.net.host.HostService;
82import org.onosproject.store.serializers.KryoNamespaces;
83import org.onosproject.store.service.EventuallyConsistentMap;
84import org.onosproject.store.service.StorageService;
85import org.onosproject.store.service.WallClockTimestamp;
86import org.onosproject.vtn.VTNService;
87import org.onosproject.vtnrsc.SegmentationId;
88import org.onosproject.vtnrsc.TenantNetwork;
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
95import com.google.common.collect.Sets;
96
97/**
98 * Provides implementation of VTNService.
99 */
100@Component(immediate = true)
101@Service
102public class VTNManager implements VTNService {
103 private final Logger log = getLogger(getClass());
104
105 private static final String APP_ID = "org.onosproject.app.vtn";
106 private ScheduledExecutorService backgroundService;
107 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
108 protected DeviceService deviceService;
109 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
110 protected HostService hostService;
111 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
112 protected FlowRuleService flowRuleService;
113 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
114 protected CoreService coreService;
115 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
116 protected StorageService storageService;
117 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
118 protected TenantNetworkService tenantNetworkService;
119 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
120 protected VirtualPortService virtualPortService;
121 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
122 protected DriverService driverService;
123 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
124 protected FlowObjectiveService flowObjectiveService;
CNluciusa66c3972015-09-06 20:31:29 +0800125 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
126 protected FlowObjectiveStore flowObjectiveStore;
127 protected ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700128 private EventuallyConsistentMap<HostId, SegmentationId> binding;
129 private ApplicationId appId;
130 private HostListener hostListener = new InnerHostListener();
131 private DeviceListener deviceListener = new InnerDeviceListener();
132 private static final String IFACEID = "ifaceid";
133 private static final String PORT_HEAD = "vxlan";
134 private static final String DEFAULT_BRIDGE_NAME = "br-int";
135 private static final String CONTROLLER_IP_KEY = "ipaddress";
136 private static final int DEFAULT_MAC_PRIORITY = 0x0000;
137 private static final int MAC_PRIORITY = 0xffff;
138 private static final int DEFAULT_PORT_PRIORITY = 0x0000;
139 private static final int PORT_PRIORITY = 0xffff;
140 private static final String SWITCH_CHANNEL_ID = "channelId";
CNluciusa66c3972015-09-06 20:31:29 +0800141 private static final String DRIVER_NAME = "onosfw";
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700142
143 @Activate
144 public void activate() {
145 KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
146 .register(KryoNamespaces.API);
147 appId = coreService.registerApplication(APP_ID);
148 deviceService.addListener(deviceListener);
149 hostService.addListener(hostListener);
150 backgroundService = newSingleThreadScheduledExecutor(groupedThreads("onos-apps/vtn",
151 "manager-background"));
152 binding = storageService
153 .<HostId, SegmentationId>eventuallyConsistentMapBuilder()
154 .withName("all_tunnel").withSerializer(serializer)
155 .withTimestampProvider((k, v) -> new WallClockTimestamp())
156 .build();
157 log.info("Started");
158 }
159
160 @Deactivate
161 public void deactivate() {
162 backgroundService.shutdown();
163 binding.destroy();
164 log.info("Stopped");
165 }
166
167 @Override
168 public void onServerDetected(Device device) {
169 Iterable<Device> devices = deviceService.getAvailableDevices();
170 DriverHandler handler = driverService.createHandler(device.id());
171 BridgeConfig bridgeConfig = handler.behaviour(BridgeConfig.class);
172 bridgeConfig.addBridge(BridgeName.bridgeName(DEFAULT_BRIDGE_NAME));
173 String ipAddress = device.annotations().value(CONTROLLER_IP_KEY);
174 IpAddress ip = IpAddress.valueOf(ipAddress);
175 Sets.newHashSet(devices).stream()
176 .filter(d -> Device.Type.CONTROLLER == d.type())
CNluciusa66c3972015-09-06 20:31:29 +0800177 .filter(d -> !device.id().equals(d.id())).forEach(d -> {
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700178 String ipAddress1 = d.annotations()
179 .value(CONTROLLER_IP_KEY);
180 IpAddress ip1 = IpAddress.valueOf(ipAddress1);
181 applyTunnelConfig(ip, ip1, handler);
182 DriverHandler handler1 = driverService
183 .createHandler(d.id());
184 applyTunnelConfig(ip1, ip, handler1);
CNluciusa66c3972015-09-06 20:31:29 +0800185
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700186 });
187 }
188
189 @Override
190 public void onServerVanished(Device device) {
191 Iterable<Device> devices = deviceService.getAvailableDevices();
192 String ipAddress = device.annotations().value(CONTROLLER_IP_KEY);
193 IpAddress dst = IpAddress.valueOf(ipAddress);
194 Sets.newHashSet(devices).stream()
195 .filter(d -> d.type() == Device.Type.CONTROLLER)
196 .filter(d -> !device.id().equals(d.id())).forEach(d -> {
197 String ipAddress1 = d.annotations()
198 .value(CONTROLLER_IP_KEY);
199 DriverHandler handler = driverService.createHandler(d.id());
200 IpAddress src = IpAddress.valueOf(ipAddress1);
201 removeTunnelConfig(src, dst, handler);
202 });
203 }
204
205 private void applyTunnelConfig(IpAddress src, IpAddress dst,
206 DriverHandler handler) {
207 TunnelEndPoint tunnelAsSrc = IpTunnelEndPoint.ipTunnelPoint(src);
208 TunnelEndPoint tunnelAsDst = IpTunnelEndPoint.ipTunnelPoint(dst);
209 TunnelDescription tunnel = new DefaultTunnelDescription(
210 tunnelAsSrc,
211 tunnelAsDst,
212 TunnelDescription.Type.VXLAN,
213 null);
214 TunnelConfig config = handler.behaviour(TunnelConfig.class);
215 config.createTunnel(tunnel);
216 }
217
218 private void removeTunnelConfig(IpAddress src, IpAddress dst,
219 DriverHandler handler) {
220 TunnelEndPoint tunnelAsSrc = IpTunnelEndPoint.ipTunnelPoint(src);
221 TunnelEndPoint tunnelAsDst = IpTunnelEndPoint.ipTunnelPoint(dst);
222 TunnelDescription tunnel = new DefaultTunnelDescription(
223 tunnelAsSrc,
224 tunnelAsDst,
225 TunnelDescription.Type.VXLAN,
226 null);
227 TunnelConfig config = handler.behaviour(TunnelConfig.class);
228 config.removeTunnel(tunnel);
229 }
230
231 @Override
232 public void onOvsDetected(Device device) {
233 programMacDefaultRules(device.id(), appId, Objective.Operation.ADD);
234 programPortDefaultRules(device.id(), appId, Objective.Operation.ADD);
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700235 }
236
237 @Override
238 public void onOvsVanished(Device device) {
239 programMacDefaultRules(device.id(), appId, Objective.Operation.REMOVE);
240 programPortDefaultRules(device.id(), appId, Objective.Operation.REMOVE);
241 }
242
243 @Override
244 public void onHostDetected(Host host) {
245 String ifaceId = host.annotations().value(IFACEID);
246 DeviceId deviceId = host.location().deviceId();
247 String currentControllerIp = getControllerIpOfSwitch(deviceId);
248 Iterable<Device> devices = deviceService.getAvailableDevices();
249 VirtualPortId portId = VirtualPortId.portId(ifaceId);
250 VirtualPort port = virtualPortService.getPort(portId);
251 TenantNetwork network = tenantNetworkService
252 .getNetwork(port.networkId());
253 String tunnelName = "vxlan-" + currentControllerIp;
254 binding.put(host.id(), network.segmentationId());
255 List<Port> allPorts = deviceService.getPorts(deviceId);
256 PortNumber inPort = host.location().port();
CNluciusa66c3972015-09-06 20:31:29 +0800257 List<PortNumber> localVmPorts = getLocalPorts(deviceId, ifaceId);
258 List<PortNumber> localTunnelPorts = new ArrayList<>();
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700259 Sets.newHashSet(allPorts.iterator()).stream()
260 .filter(p -> !p.number().equals(PortNumber.LOCAL)).forEach(p -> {
CNluciusa66c3972015-09-06 20:31:29 +0800261 if (p.annotations().value("portName").startsWith(PORT_HEAD)) {
262 localTunnelPorts.add(p.number());
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700263 }
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700264 });
265
CNluciusa66c3972015-09-06 20:31:29 +0800266 localVmPorts.forEach(lp -> programLocalBcastRules(deviceId, network.segmentationId(), lp, localVmPorts,
267 localTunnelPorts, appId, Objective.Operation.ADD));
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700268 programLocalOut(deviceId, network.segmentationId(), inPort, host.mac(),
269 appId, Objective.Operation.ADD);
CNluciusa66c3972015-09-06 20:31:29 +0800270 localTunnelPorts
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700271 .forEach(tp -> programTunnelFloodOut(deviceId,
272 network.segmentationId(),
CNluciusa66c3972015-09-06 20:31:29 +0800273 tp, localVmPorts,
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700274 appId,
275 Objective.Operation.ADD));
276 Sets.newHashSet(devices).stream()
277 .filter(d -> d.type() == Device.Type.CONTROLLER).forEach(d -> {
278 DriverHandler handler = driverService.createHandler(d.id());
279 BridgeConfig bridgeConfig = handler
280 .behaviour(BridgeConfig.class);
281 Collection<BridgeDescription> bridgeDescriptions = bridgeConfig
282 .getBridges();
283
284 Iterator<BridgeDescription> it = bridgeDescriptions
285 .iterator();
286 if (it.hasNext()) {
287 BridgeDescription sw = it.next();
288 Set<PortNumber> ports = bridgeConfig.getPortNumbers();
289 ports.stream()
290 .filter(p -> p.name()
291 .equalsIgnoreCase(tunnelName))
CNluciusa66c3972015-09-06 20:31:29 +0800292 .forEach(p -> {
293 programTunnelOut(sw.deviceId(),
294 network.segmentationId(), p,
295 host.mac(), appId,
296 Objective.Operation.ADD);
297 });
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700298 }
299 });
300 programLocalIn(deviceId, network.segmentationId(), inPort, host.mac(),
301 appId, Objective.Operation.ADD);
CNluciusa66c3972015-09-06 20:31:29 +0800302 localTunnelPorts
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700303 .forEach(tp -> programTunnelIn(deviceId,
304 network.segmentationId(),
CNluciusa66c3972015-09-06 20:31:29 +0800305 tp, inPort, host.mac(),
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700306 appId, Objective.Operation.ADD));
307
308 }
309
310 @Override
311 public void onHostVanished(Host host) {
CNluciusa66c3972015-09-06 20:31:29 +0800312 String ifaceId = host.annotations().value(IFACEID);
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700313 SegmentationId segId = binding.remove(host.id());
314 DeviceId deviceId = host.location().deviceId();
315 String currentControllerIp = getControllerIpOfSwitch(deviceId);
316 Iterable<Device> devices = deviceService.getAvailableDevices();
CNluciusa66c3972015-09-06 20:31:29 +0800317
318 String tunnelName = "vxlan-" + currentControllerIp;
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700319 List<Port> allPorts = deviceService.getPorts(deviceId);
320 PortNumber inPort = host.location().port();
CNluciusa66c3972015-09-06 20:31:29 +0800321
322 List<PortNumber> localTunnelPorts = new ArrayList<>();
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700323 Sets.newHashSet(allPorts.iterator()).stream()
324 .filter(p -> !p.number().equals(PortNumber.LOCAL)).forEach(p -> {
CNluciusa66c3972015-09-06 20:31:29 +0800325 if (p.annotations().value("portName").startsWith(PORT_HEAD)) {
326 localTunnelPorts.add(p.number());
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700327 }
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700328 });
329
CNluciusa66c3972015-09-06 20:31:29 +0800330 List<PortNumber> localVmPorts = getLocalPorts(deviceId, ifaceId);
331 localVmPorts.add(inPort);
332 localVmPorts.forEach(lp -> programLocalBcastRules(deviceId, segId, lp, localVmPorts,
333 localTunnelPorts, appId, Objective.Operation.REMOVE));
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700334 programLocalOut(deviceId, segId, inPort, host.mac(),
335 appId, Objective.Operation.REMOVE);
CNluciusa66c3972015-09-06 20:31:29 +0800336 localTunnelPorts
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700337 .forEach(tp -> programTunnelFloodOut(deviceId,
338 segId,
CNluciusa66c3972015-09-06 20:31:29 +0800339 tp, localVmPorts,
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700340 appId,
341 Objective.Operation.REMOVE));
342 Sets.newHashSet(devices).stream()
343 .filter(d -> d.type() == Device.Type.CONTROLLER).forEach(d -> {
344 DriverHandler handler = driverService.createHandler(d.id());
345 BridgeConfig bridgeConfig = handler
346 .behaviour(BridgeConfig.class);
347 Collection<BridgeDescription> bridgeDescriptions = bridgeConfig
348 .getBridges();
349
350 Iterator<BridgeDescription> it = bridgeDescriptions
351 .iterator();
352 if (it.hasNext()) {
353 BridgeDescription sw = it.next();
354 Set<PortNumber> ports = bridgeConfig.getPortNumbers();
355 ports.stream()
356 .filter(p -> p.name()
CNluciusa66c3972015-09-06 20:31:29 +0800357 .equalsIgnoreCase(tunnelName))
358 .forEach(p -> {
359 programTunnelOut(sw.deviceId(),
360 segId, p,
361 host.mac(), appId,
362 Objective.Operation.REMOVE);
363 });
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700364 }
365 });
366 programLocalIn(deviceId, segId, inPort, host.mac(),
367 appId, Objective.Operation.REMOVE);
CNluciusa66c3972015-09-06 20:31:29 +0800368 localTunnelPorts
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700369 .forEach(tp -> programTunnelIn(deviceId,
370 segId,
CNluciusa66c3972015-09-06 20:31:29 +0800371 tp, inPort, host.mac(),
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700372 appId, Objective.Operation.REMOVE));
373 }
374
375 private class InnerDeviceListener implements DeviceListener {
376
377 @Override
378 public void event(DeviceEvent event) {
379 Device device = event.subject();
380 if (Device.Type.CONTROLLER == device.type()
381 && DeviceEvent.Type.DEVICE_ADDED == event.type()) {
382 backgroundService.execute(() -> {
383 onServerDetected(device);
384 });
385 } else if (Device.Type.CONTROLLER == device.type()
386 && DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED == event
387 .type()) {
388 backgroundService.execute(() -> {
389 onServerVanished(device);
390 });
391 } else if (Device.Type.SWITCH == device.type()
392 && DeviceEvent.Type.DEVICE_ADDED == event.type()) {
393 backgroundService.execute(() -> {
394 onOvsDetected(device);
395 });
396 } else if (Device.Type.SWITCH == device.type()
397 && DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED == event
398 .type()) {
399 backgroundService.execute(() -> {
400 onOvsVanished(device);
401 });
402 } else {
403 log.info("Do nothing for this device type");
404 }
405 }
406
407 }
408
409 private class InnerHostListener implements HostListener {
410
411 @Override
412 public void event(HostEvent event) {
413 Host host = event.subject();
414 if (HostEvent.Type.HOST_ADDED == event.type()) {
415 backgroundService.execute(() -> {
416 onHostDetected(host);
417 });
418 } else if (HostEvent.Type.HOST_REMOVED == event.type()) {
419 backgroundService.execute(() -> {
420 onHostVanished(host);
421 });
422 } else if (HostEvent.Type.HOST_UPDATED == event.type()) {
423 backgroundService.execute(() -> {
424 onHostVanished(host);
425 onHostDetected(host);
426 });
427 }
428 }
429
430 }
431
432 // Used to forward the flows to the local VM.
433 private void programLocalOut(DeviceId dpid, SegmentationId segmentationId,
434 PortNumber outPort, MacAddress sourceMac,
435 ApplicationId appid,
436 Objective.Operation type) {
437 TrafficSelector selector = DefaultTrafficSelector.builder()
CNluciusa66c3972015-09-06 20:31:29 +0800438 .matchTunnelId(Long.parseLong(segmentationId.toString()))
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700439 .matchEthDst(sourceMac).build();
440 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700441 .setOutput(outPort).build();
442 ForwardingObjective.Builder objective = DefaultForwardingObjective
443 .builder().withTreatment(treatment).withSelector(selector)
444 .fromApp(appId).withFlag(Flag.SPECIFIC)
445 .withPriority(MAC_PRIORITY);
446 if (type.equals(Objective.Operation.ADD)) {
CNluciusa66c3972015-09-06 20:31:29 +0800447 flowServiceForward(dpid, objective.add());
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700448 } else {
CNluciusa66c3972015-09-06 20:31:29 +0800449 flowServiceForward(dpid, objective.remove());
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700450 }
451
452 }
453
454 // Used to forward the flows into the VXLAN tunnel.
455 private void programTunnelOut(DeviceId dpid, SegmentationId segmentationId,
456 PortNumber tunnelOutPort, MacAddress dstMac,
457 ApplicationId appid,
458 Objective.Operation type) {
459 TrafficSelector selector = DefaultTrafficSelector.builder()
460 .matchEthDst(dstMac).add(Criteria.matchTunnelId(Long
461 .parseLong(segmentationId.toString())))
462 .build();
463 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
464
465 .setOutput(tunnelOutPort).build();
466 ForwardingObjective.Builder objective = DefaultForwardingObjective
467 .builder().withTreatment(treatment).withSelector(selector)
468 .fromApp(appId).withFlag(Flag.SPECIFIC)
469 .withPriority(MAC_PRIORITY);
470 if (type.equals(Objective.Operation.ADD)) {
CNluciusa66c3972015-09-06 20:31:29 +0800471 flowServiceForward(dpid, objective.add());
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700472 } else {
CNluciusa66c3972015-09-06 20:31:29 +0800473 flowServiceForward(dpid, objective.remove());
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700474 }
475
476 }
477
478 // Used to forward multicast flows to remote VMs of the same tenant via
479 // VXLAN tunnel.
CNluciusa66c3972015-09-06 20:31:29 +0800480 private void programTunnelFloodOut(DeviceId deviceId,
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700481 SegmentationId segmentationId,
482 PortNumber ofPortOut,
CNluciusa66c3972015-09-06 20:31:29 +0800483 List<PortNumber> localVmPorts,
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700484 ApplicationId appid,
485 Objective.Operation type) {
486 TrafficSelector selector = DefaultTrafficSelector.builder()
487 .matchInPort(ofPortOut)
488
489 .add(Criteria.matchTunnelId(Long.parseLong(segmentationId
490 .toString()))).matchEthDst(MacAddress.BROADCAST)
491 .build();
492 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
CNluciusa66c3972015-09-06 20:31:29 +0800493
494 for (PortNumber outPort : localVmPorts) {
495 treatment.setOutput(outPort);
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700496 }
497
498 ForwardingObjective.Builder objective = DefaultForwardingObjective
499 .builder().withTreatment(treatment.build())
500 .withSelector(selector).fromApp(appId).makePermanent()
501 .withFlag(Flag.SPECIFIC).withPriority(MAC_PRIORITY);
502 if (type.equals(Objective.Operation.ADD)) {
CNluciusa66c3972015-09-06 20:31:29 +0800503 flowServiceForward(deviceId, objective.add());
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700504 } else {
CNluciusa66c3972015-09-06 20:31:29 +0800505 flowServiceForward(deviceId, objective.remove());
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700506 }
507 }
508
509 // Applies default flows to mac table.
510 private void programMacDefaultRules(DeviceId dpid, ApplicationId appid,
511 Objective.Operation type) {
512 TrafficSelector selector = DefaultTrafficSelector.builder().build();
513 TrafficTreatment treatment = DefaultTrafficTreatment.builder().drop()
514 .build();
515 ForwardingObjective.Builder objective = DefaultForwardingObjective
516 .builder().withTreatment(treatment).withSelector(selector)
517 .fromApp(appId).makePermanent().withFlag(Flag.SPECIFIC)
518 .withPriority(DEFAULT_MAC_PRIORITY);
519 if (type.equals(Objective.Operation.ADD)) {
CNluciusa66c3972015-09-06 20:31:29 +0800520 flowServiceForward(dpid, objective.add());
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700521 } else {
CNluciusa66c3972015-09-06 20:31:29 +0800522 flowServiceForward(dpid, objective.remove());
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700523 }
524 }
525
526 // Used to forward the flows to the local VMs with the same tenant.
CNluciusa66c3972015-09-06 20:31:29 +0800527 private void programLocalBcastRules(DeviceId deviceId,
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700528 SegmentationId segmentationId,
CNluciusa66c3972015-09-06 20:31:29 +0800529 PortNumber inPort,
530 List<PortNumber> localVmPorts,
531 List<PortNumber> localTunnelPorts,
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700532 ApplicationId appid,
533 Objective.Operation type) {
534 TrafficSelector selector = DefaultTrafficSelector.builder()
535 .matchInPort(inPort).matchEthDst(MacAddress.BROADCAST)
536 .add(Criteria.matchTunnelId(Long
537 .parseLong(segmentationId.toString())))
538 .build();
539 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
CNluciusa66c3972015-09-06 20:31:29 +0800540 for (PortNumber outPort : localVmPorts) {
541 if (inPort != outPort) {
542 treatment.setOutput(outPort);
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700543 }
544 }
CNluciusa66c3972015-09-06 20:31:29 +0800545 for (PortNumber outport : localTunnelPorts) {
546 treatment.setOutput(outport);
547 }
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700548 ForwardingObjective.Builder objective = DefaultForwardingObjective
549 .builder().withTreatment(treatment.build())
550 .withSelector(selector).fromApp(appId).makePermanent()
551 .withFlag(Flag.SPECIFIC).withPriority(MAC_PRIORITY);
552 if (type.equals(Objective.Operation.ADD)) {
CNluciusa66c3972015-09-06 20:31:29 +0800553 flowServiceForward(deviceId, objective.add());
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700554 } else {
CNluciusa66c3972015-09-06 20:31:29 +0800555 flowServiceForward(deviceId, objective.remove());
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700556 }
557 }
558
559 // Used to apply local entry flow.
560 private void programLocalIn(DeviceId dpid, SegmentationId segmentationId,
561 PortNumber inPort, MacAddress srcMac,
562 ApplicationId appid, Objective.Operation type) {
563 TrafficSelector selector = DefaultTrafficSelector.builder()
564 .matchInPort(inPort).matchEthSrc(srcMac).build();
565 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
566 treatment.add(Instructions.modTunnelId(Long.parseLong(segmentationId
567 .toString())));
568 ForwardingObjective.Builder objective = DefaultForwardingObjective
569 .builder().withTreatment(treatment.build())
570 .withSelector(selector).fromApp(appId).makePermanent()
571 .withFlag(Flag.SPECIFIC).withPriority(PORT_PRIORITY);
572 if (type.equals(Objective.Operation.ADD)) {
CNluciusa66c3972015-09-06 20:31:29 +0800573 flowServiceForward(dpid, objective.add());
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700574 } else {
CNluciusa66c3972015-09-06 20:31:29 +0800575 flowServiceForward(dpid, objective.remove());
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700576 }
577 }
578
579 // Used to forward the flows from the egress tunnel to the VM.
580 private void programTunnelIn(DeviceId dpid, SegmentationId segmentationId,
581 PortNumber tunnelInPort, PortNumber outPort,
582 MacAddress sourceMac, ApplicationId appid,
583 Objective.Operation type) {
584 TrafficSelector selector = DefaultTrafficSelector.builder()
585 .matchInPort(tunnelInPort).add(Criteria.matchTunnelId(Long
586 .parseLong(segmentationId.toString())))
587 .build();
588 TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
589
590 ForwardingObjective.Builder objective = DefaultForwardingObjective
591 .builder().withTreatment(treatment).withSelector(selector)
592 .fromApp(appId).makePermanent().withFlag(Flag.SPECIFIC)
593 .withPriority(PORT_PRIORITY);
594 if (type.equals(Objective.Operation.ADD)) {
CNluciusa66c3972015-09-06 20:31:29 +0800595 flowServiceForward(dpid, objective.add());
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700596 } else {
CNluciusa66c3972015-09-06 20:31:29 +0800597 flowServiceForward(dpid, objective.remove());
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700598 }
599 }
600
601 // Applies the default flows to port table.
602 private void programPortDefaultRules(DeviceId dpid, ApplicationId appid,
603 Objective.Operation type) {
604 TrafficSelector selector = DefaultTrafficSelector.builder().build();
605 TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
606 ForwardingObjective.Builder objective = DefaultForwardingObjective
607 .builder().withTreatment(treatment).withSelector(selector)
608 .fromApp(appId).makePermanent().withFlag(Flag.SPECIFIC)
609 .withPriority(DEFAULT_PORT_PRIORITY);
610 if (type.equals(Objective.Operation.ADD)) {
CNluciusa66c3972015-09-06 20:31:29 +0800611 flowServiceForward(dpid, objective.add());
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700612 } else {
CNluciusa66c3972015-09-06 20:31:29 +0800613 flowServiceForward(dpid, objective.remove());
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700614 }
615 }
616
617 // Used to get channelId from the device annotations.
618 private String getControllerIpOfSwitch(DeviceId deviceId) {
619 Device device = deviceService.getDevice(deviceId);
620 String url = device.annotations().value(SWITCH_CHANNEL_ID);
621 return url.substring(0, url.lastIndexOf(":"));
622 }
623
CNluciusa66c3972015-09-06 20:31:29 +0800624 private Iterable<String> getIfaceIds(String ifaceId) {
625 VirtualPortId portId = VirtualPortId.portId(ifaceId);
626 VirtualPort port = virtualPortService.getPort(portId);
627 TenantNetwork network = tenantNetworkService
628 .getNetwork(port.networkId());
Sho SHIMIZU6cfc02d2015-09-11 11:19:11 -0700629 Collection<String> ifaceIds = new HashSet<>();
CNluciusa66c3972015-09-06 20:31:29 +0800630 Collection<VirtualPort> ports = virtualPortService
631 .getPorts(network.id());
632 Sets.newHashSet(ports).stream()
633 .forEach(p -> ifaceIds.add(p.portId().portId()));
634 return ifaceIds;
635 }
636
637 private List<PortNumber> getLocalPorts(DeviceId deviceId, String ifaceId) {
638 DriverHandler handler = driverService
639 .createHandler(getController(deviceId));
640 BridgeConfig bridgeConfig = handler.behaviour(BridgeConfig.class);
641 Iterable<String> ifaceIds = getIfaceIds(ifaceId);
642 return bridgeConfig.getLocalPorts(ifaceIds);
643 }
644
645 private DeviceId getController(DeviceId deviceId) {
646 Iterable<Device> devices = deviceService.getAvailableDevices();
647 for (Device device : devices) {
648 if (device.type() == Device.Type.CONTROLLER && device.id()
649 .toString().contains(getControllerIpOfSwitch(deviceId))) {
650 return device.id();
651 }
652 }
653 log.info("Can not find controller for device : {}", deviceId);
654 return null;
655 }
656
657 //Used to apply flowRule
658 private void flowServiceForward(DeviceId deviceId, ForwardingObjective forwardingObjective) {
659 Driver driver = driverService.getDriver(DRIVER_NAME);
660 Pipeliner pipeLiner = driver.createBehaviour(new DefaultDriverData(driver, deviceId), Pipeliner.class);
661 if (pipeLiner != null) {
662 final PipelinerContext context = new InnerPipelineContext();
663 pipeLiner.init(deviceId, context);
664 pipeLiner.forward(forwardingObjective);
665 }
666 }
667
668 // Processing context for initializing pipeline driver behaviours.
669 private class InnerPipelineContext implements PipelinerContext {
670 @Override
671 public ServiceDirectory directory() {
672 return serviceDirectory;
673 }
674
675 @Override
676 public FlowObjectiveStore store() {
677 return flowObjectiveStore;
678 }
679 }
680
Sho SHIMIZU7d2e48e2015-09-01 17:37:00 -0700681}