lishuai
Committed by Gerrit Code Review

[ONOS-2831] Refactor L2 code according to the L3 plan.

Change-Id: Ibc9dc47a18208b9b1602261064a33bc63b131fc3
Showing 20 changed files with 1432 additions and 679 deletions
1 -/*
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 - */
16 -package org.onosproject.vtn.impl;
17 -
18 -import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
19 -import static org.onlab.util.Tools.groupedThreads;
20 -import static org.slf4j.LoggerFactory.getLogger;
21 -
22 -import java.util.ArrayList;
23 -import java.util.Collection;
24 -import java.util.Collections;
25 -import java.util.Iterator;
26 -import java.util.List;
27 -import java.util.Set;
28 -import java.util.concurrent.ScheduledExecutorService;
29 -import java.util.stream.Collectors;
30 -
31 -import org.apache.felix.scr.annotations.Activate;
32 -import org.apache.felix.scr.annotations.Component;
33 -import org.apache.felix.scr.annotations.Deactivate;
34 -import org.apache.felix.scr.annotations.Reference;
35 -import org.apache.felix.scr.annotations.ReferenceCardinality;
36 -import org.apache.felix.scr.annotations.Service;
37 -import org.onlab.osgi.DefaultServiceDirectory;
38 -import org.onlab.osgi.ServiceDirectory;
39 -import org.onlab.packet.IpAddress;
40 -import org.onlab.packet.MacAddress;
41 -import org.onlab.util.KryoNamespace;
42 -import org.onosproject.core.ApplicationId;
43 -import org.onosproject.core.CoreService;
44 -import org.onosproject.net.Device;
45 -import org.onosproject.net.DeviceId;
46 -import org.onosproject.net.Host;
47 -import org.onosproject.net.HostId;
48 -import org.onosproject.net.Port;
49 -import org.onosproject.net.PortNumber;
50 -import org.onosproject.net.behaviour.BridgeConfig;
51 -import org.onosproject.net.behaviour.BridgeDescription;
52 -import org.onosproject.net.behaviour.BridgeName;
53 -import org.onosproject.net.behaviour.DefaultTunnelDescription;
54 -import org.onosproject.net.behaviour.IpTunnelEndPoint;
55 -import org.onosproject.net.behaviour.Pipeliner;
56 -import org.onosproject.net.behaviour.PipelinerContext;
57 -import org.onosproject.net.behaviour.TunnelConfig;
58 -import org.onosproject.net.behaviour.TunnelDescription;
59 -import org.onosproject.net.behaviour.TunnelEndPoint;
60 -import org.onosproject.net.device.DeviceEvent;
61 -import org.onosproject.net.device.DeviceListener;
62 -import org.onosproject.net.device.DeviceService;
63 -import org.onosproject.net.driver.DefaultDriverData;
64 -import org.onosproject.net.driver.Driver;
65 -import org.onosproject.net.driver.DriverHandler;
66 -import org.onosproject.net.driver.DriverService;
67 -import org.onosproject.net.flow.DefaultTrafficSelector;
68 -import org.onosproject.net.flow.DefaultTrafficTreatment;
69 -import org.onosproject.net.flow.FlowRuleService;
70 -import org.onosproject.net.flow.TrafficSelector;
71 -import org.onosproject.net.flow.TrafficTreatment;
72 -import org.onosproject.net.flow.criteria.Criteria;
73 -import org.onosproject.net.flow.instructions.Instructions;
74 -import org.onosproject.net.flowobjective.DefaultForwardingObjective;
75 -import org.onosproject.net.flowobjective.FlowObjectiveService;
76 -import org.onosproject.net.flowobjective.FlowObjectiveStore;
77 -import org.onosproject.net.flowobjective.ForwardingObjective;
78 -import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
79 -import org.onosproject.net.flowobjective.Objective;
80 -import org.onosproject.net.host.HostEvent;
81 -import org.onosproject.net.host.HostListener;
82 -import org.onosproject.net.host.HostService;
83 -import org.onosproject.store.serializers.KryoNamespaces;
84 -import org.onosproject.store.service.EventuallyConsistentMap;
85 -import org.onosproject.store.service.StorageService;
86 -import org.onosproject.store.service.WallClockTimestamp;
87 -import org.onosproject.vtn.VTNService;
88 -import org.onosproject.vtnrsc.SegmentationId;
89 -import org.onosproject.vtnrsc.TenantNetwork;
90 -import org.onosproject.vtnrsc.VirtualPort;
91 -import org.onosproject.vtnrsc.VirtualPortId;
92 -import org.onosproject.vtnrsc.tenantnetwork.TenantNetworkService;
93 -import org.onosproject.vtnrsc.virtualport.VirtualPortService;
94 -import org.slf4j.Logger;
95 -
96 -import com.google.common.collect.Sets;
97 -
98 -/**
99 - * Provides implementation of VTNService.
100 - */
101 -@Component(immediate = true)
102 -@Service
103 -public class VTNManager implements VTNService {
104 - private final Logger log = getLogger(getClass());
105 -
106 - private static final String APP_ID = "org.onosproject.app.vtn";
107 - private ScheduledExecutorService backgroundService;
108 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
109 - protected DeviceService deviceService;
110 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
111 - protected HostService hostService;
112 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
113 - protected FlowRuleService flowRuleService;
114 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
115 - protected CoreService coreService;
116 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
117 - protected StorageService storageService;
118 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
119 - protected TenantNetworkService tenantNetworkService;
120 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
121 - protected VirtualPortService virtualPortService;
122 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
123 - protected DriverService driverService;
124 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
125 - protected FlowObjectiveService flowObjectiveService;
126 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
127 - protected FlowObjectiveStore flowObjectiveStore;
128 - protected ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
129 - private EventuallyConsistentMap<HostId, SegmentationId> binding;
130 - private ApplicationId appId;
131 - private HostListener hostListener = new InnerHostListener();
132 - private DeviceListener deviceListener = new InnerDeviceListener();
133 - private static final String IFACEID = "ifaceid";
134 - private static final String PORT_HEAD = "vxlan";
135 - private static final String DEFAULT_BRIDGE_NAME = "br-int";
136 - private static final String CONTROLLER_IP_KEY = "ipaddress";
137 - private static final int DEFAULT_MAC_PRIORITY = 0x0000;
138 - private static final int MAC_PRIORITY = 0xffff;
139 - private static final int DEFAULT_PORT_PRIORITY = 0x0000;
140 - private static final int PORT_PRIORITY = 0xffff;
141 - private static final String SWITCH_CHANNEL_ID = "channelId";
142 - private static final String DRIVER_NAME = "onosfw";
143 -
144 - @Activate
145 - public void activate() {
146 - KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
147 - .register(KryoNamespaces.API);
148 - appId = coreService.registerApplication(APP_ID);
149 - deviceService.addListener(deviceListener);
150 - hostService.addListener(hostListener);
151 - backgroundService = newSingleThreadScheduledExecutor(groupedThreads("onos-apps/vtn",
152 - "manager-background"));
153 - binding = storageService
154 - .<HostId, SegmentationId>eventuallyConsistentMapBuilder()
155 - .withName("all_tunnel").withSerializer(serializer)
156 - .withTimestampProvider((k, v) -> new WallClockTimestamp())
157 - .build();
158 - log.info("Started");
159 - }
160 -
161 - @Deactivate
162 - public void deactivate() {
163 - backgroundService.shutdown();
164 - binding.destroy();
165 - log.info("Stopped");
166 - }
167 -
168 - @Override
169 - public void onServerDetected(Device device) {
170 - Iterable<Device> devices = deviceService.getAvailableDevices();
171 - DriverHandler handler = driverService.createHandler(device.id());
172 - BridgeConfig bridgeConfig = handler.behaviour(BridgeConfig.class);
173 - bridgeConfig.addBridge(BridgeName.bridgeName(DEFAULT_BRIDGE_NAME));
174 - String ipAddress = device.annotations().value(CONTROLLER_IP_KEY);
175 - IpAddress ip = IpAddress.valueOf(ipAddress);
176 - Sets.newHashSet(devices).stream()
177 - .filter(d -> Device.Type.CONTROLLER == d.type())
178 - .filter(d -> !device.id().equals(d.id())).forEach(d -> {
179 - String ipAddress1 = d.annotations()
180 - .value(CONTROLLER_IP_KEY);
181 - IpAddress ip1 = IpAddress.valueOf(ipAddress1);
182 - applyTunnelConfig(ip, ip1, handler);
183 - DriverHandler handler1 = driverService
184 - .createHandler(d.id());
185 - applyTunnelConfig(ip1, ip, handler1);
186 -
187 - });
188 - }
189 -
190 - @Override
191 - public void onServerVanished(Device device) {
192 - Iterable<Device> devices = deviceService.getAvailableDevices();
193 - String ipAddress = device.annotations().value(CONTROLLER_IP_KEY);
194 - IpAddress dst = IpAddress.valueOf(ipAddress);
195 - Sets.newHashSet(devices).stream()
196 - .filter(d -> d.type() == Device.Type.CONTROLLER)
197 - .filter(d -> !device.id().equals(d.id())).forEach(d -> {
198 - String ipAddress1 = d.annotations()
199 - .value(CONTROLLER_IP_KEY);
200 - DriverHandler handler = driverService.createHandler(d.id());
201 - IpAddress src = IpAddress.valueOf(ipAddress1);
202 - removeTunnelConfig(src, dst, handler);
203 - });
204 - }
205 -
206 - private void applyTunnelConfig(IpAddress src, IpAddress dst,
207 - DriverHandler handler) {
208 - TunnelEndPoint tunnelAsSrc = IpTunnelEndPoint.ipTunnelPoint(src);
209 - TunnelEndPoint tunnelAsDst = IpTunnelEndPoint.ipTunnelPoint(dst);
210 - TunnelDescription tunnel = new DefaultTunnelDescription(
211 - tunnelAsSrc,
212 - tunnelAsDst,
213 - TunnelDescription.Type.VXLAN,
214 - null);
215 - TunnelConfig config = handler.behaviour(TunnelConfig.class);
216 - config.createTunnel(tunnel);
217 - }
218 -
219 - private void removeTunnelConfig(IpAddress src, IpAddress dst,
220 - DriverHandler handler) {
221 - TunnelEndPoint tunnelAsSrc = IpTunnelEndPoint.ipTunnelPoint(src);
222 - TunnelEndPoint tunnelAsDst = IpTunnelEndPoint.ipTunnelPoint(dst);
223 - TunnelDescription tunnel = new DefaultTunnelDescription(
224 - tunnelAsSrc,
225 - tunnelAsDst,
226 - TunnelDescription.Type.VXLAN,
227 - null);
228 - TunnelConfig config = handler.behaviour(TunnelConfig.class);
229 - config.removeTunnel(tunnel);
230 - }
231 -
232 - @Override
233 - public void onOvsDetected(Device device) {
234 - programMacDefaultRules(device.id(), appId, Objective.Operation.ADD);
235 - programPortDefaultRules(device.id(), appId, Objective.Operation.ADD);
236 - }
237 -
238 - @Override
239 - public void onOvsVanished(Device device) {
240 - programMacDefaultRules(device.id(), appId, Objective.Operation.REMOVE);
241 - programPortDefaultRules(device.id(), appId, Objective.Operation.REMOVE);
242 - }
243 -
244 - @Override
245 - public void onHostDetected(Host host) {
246 - String ifaceId = host.annotations().value(IFACEID);
247 - DeviceId deviceId = host.location().deviceId();
248 - String currentControllerIp = getControllerIpOfSwitch(deviceId);
249 - Iterable<Device> devices = deviceService.getAvailableDevices();
250 - VirtualPortId portId = VirtualPortId.portId(ifaceId);
251 - VirtualPort port = virtualPortService.getPort(portId);
252 - TenantNetwork network = tenantNetworkService
253 - .getNetwork(port.networkId());
254 - String tunnelName = "vxlan-" + currentControllerIp;
255 - binding.put(host.id(), network.segmentationId());
256 - List<Port> allPorts = deviceService.getPorts(deviceId);
257 - PortNumber inPort = host.location().port();
258 - List<PortNumber> localVmPorts = getLocalPorts(deviceId, ifaceId);
259 - List<PortNumber> localTunnelPorts = new ArrayList<>();
260 - Sets.newHashSet(allPorts.iterator()).stream()
261 - .filter(p -> !p.number().equals(PortNumber.LOCAL)).forEach(p -> {
262 - if (p.annotations().value("portName").startsWith(PORT_HEAD)) {
263 - localTunnelPorts.add(p.number());
264 - }
265 - });
266 -
267 - localVmPorts.forEach(lp -> programLocalBcastRules(deviceId, network.segmentationId(), lp, localVmPorts,
268 - localTunnelPorts, appId, Objective.Operation.ADD));
269 - programLocalOut(deviceId, network.segmentationId(), inPort, host.mac(),
270 - appId, Objective.Operation.ADD);
271 - localTunnelPorts
272 - .forEach(tp -> programTunnelFloodOut(deviceId,
273 - network.segmentationId(),
274 - tp, localVmPorts,
275 - appId,
276 - Objective.Operation.ADD));
277 - Sets.newHashSet(devices).stream()
278 - .filter(d -> d.type() == Device.Type.CONTROLLER).forEach(d -> {
279 - DriverHandler handler = driverService.createHandler(d.id());
280 - BridgeConfig bridgeConfig = handler
281 - .behaviour(BridgeConfig.class);
282 - Collection<BridgeDescription> bridgeDescriptions = bridgeConfig
283 - .getBridges();
284 -
285 - Iterator<BridgeDescription> it = bridgeDescriptions
286 - .iterator();
287 - if (it.hasNext()) {
288 - BridgeDescription sw = it.next();
289 - Set<PortNumber> ports = bridgeConfig.getPortNumbers();
290 - ports.stream()
291 - .filter(p -> p.name()
292 - .equalsIgnoreCase(tunnelName))
293 - .forEach(p -> programTunnelOut(sw.deviceId(),
294 - network.segmentationId(), p,
295 - host.mac(), appId,
296 - Objective.Operation.ADD));
297 - }
298 - });
299 - programLocalIn(deviceId, network.segmentationId(), inPort, host.mac(),
300 - appId, Objective.Operation.ADD);
301 - localTunnelPorts
302 - .forEach(tp -> programTunnelIn(deviceId,
303 - network.segmentationId(),
304 - tp, inPort, host.mac(),
305 - appId, Objective.Operation.ADD));
306 -
307 - }
308 -
309 - @Override
310 - public void onHostVanished(Host host) {
311 - String ifaceId = host.annotations().value(IFACEID);
312 - SegmentationId segId = binding.remove(host.id());
313 - DeviceId deviceId = host.location().deviceId();
314 - String currentControllerIp = getControllerIpOfSwitch(deviceId);
315 - Iterable<Device> devices = deviceService.getAvailableDevices();
316 -
317 - String tunnelName = "vxlan-" + currentControllerIp;
318 - List<Port> allPorts = deviceService.getPorts(deviceId);
319 - PortNumber inPort = host.location().port();
320 -
321 - List<PortNumber> localTunnelPorts = new ArrayList<>();
322 - Sets.newHashSet(allPorts.iterator()).stream()
323 - .filter(p -> !p.number().equals(PortNumber.LOCAL)).forEach(p -> {
324 - if (p.annotations().value("portName").startsWith(PORT_HEAD)) {
325 - localTunnelPorts.add(p.number());
326 - }
327 - });
328 -
329 - List<PortNumber> localVmPorts = getLocalPorts(deviceId, ifaceId);
330 - localVmPorts.add(inPort);
331 - localVmPorts.forEach(lp -> programLocalBcastRules(deviceId, segId, lp, localVmPorts,
332 - localTunnelPorts, appId, Objective.Operation.REMOVE));
333 - programLocalOut(deviceId, segId, inPort, host.mac(),
334 - appId, Objective.Operation.REMOVE);
335 - localTunnelPorts
336 - .forEach(tp -> programTunnelFloodOut(deviceId,
337 - segId,
338 - tp, localVmPorts,
339 - appId,
340 - Objective.Operation.REMOVE));
341 - Sets.newHashSet(devices).stream()
342 - .filter(d -> d.type() == Device.Type.CONTROLLER).forEach(d -> {
343 - DriverHandler handler = driverService.createHandler(d.id());
344 - BridgeConfig bridgeConfig = handler
345 - .behaviour(BridgeConfig.class);
346 - Collection<BridgeDescription> bridgeDescriptions = bridgeConfig
347 - .getBridges();
348 -
349 - Iterator<BridgeDescription> it = bridgeDescriptions
350 - .iterator();
351 - if (it.hasNext()) {
352 - BridgeDescription sw = it.next();
353 - Set<PortNumber> ports = bridgeConfig.getPortNumbers();
354 - ports.stream()
355 - .filter(p -> p.name()
356 - .equalsIgnoreCase(tunnelName))
357 - .forEach(p -> programTunnelOut(sw.deviceId(),
358 - segId, p,
359 - host.mac(), appId,
360 - Objective.Operation.REMOVE));
361 - }
362 - });
363 - programLocalIn(deviceId, segId, inPort, host.mac(),
364 - appId, Objective.Operation.REMOVE);
365 - localTunnelPorts
366 - .forEach(tp -> programTunnelIn(deviceId,
367 - segId,
368 - tp, inPort, host.mac(),
369 - appId, Objective.Operation.REMOVE));
370 - }
371 -
372 - private class InnerDeviceListener implements DeviceListener {
373 -
374 - @Override
375 - public void event(DeviceEvent event) {
376 - Device device = event.subject();
377 - if (Device.Type.CONTROLLER == device.type()
378 - && DeviceEvent.Type.DEVICE_ADDED == event.type()) {
379 - backgroundService.execute(() -> onServerDetected(device));
380 - } else if (Device.Type.CONTROLLER == device.type()
381 - && DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED == event
382 - .type()) {
383 - backgroundService.execute(() -> onServerVanished(device));
384 - } else if (Device.Type.SWITCH == device.type()
385 - && DeviceEvent.Type.DEVICE_ADDED == event.type()) {
386 - backgroundService.execute(() -> onOvsDetected(device));
387 - } else if (Device.Type.SWITCH == device.type()
388 - && DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED == event
389 - .type()) {
390 - backgroundService.execute(() -> onOvsVanished(device));
391 - } else {
392 - log.info("Do nothing for this device type");
393 - }
394 - }
395 -
396 - }
397 -
398 - private class InnerHostListener implements HostListener {
399 -
400 - @Override
401 - public void event(HostEvent event) {
402 - Host host = event.subject();
403 - if (HostEvent.Type.HOST_ADDED == event.type()) {
404 - backgroundService.execute(() -> onHostDetected(host));
405 - } else if (HostEvent.Type.HOST_REMOVED == event.type()) {
406 - backgroundService.execute(() -> onHostVanished(host));
407 - } else if (HostEvent.Type.HOST_UPDATED == event.type()) {
408 - backgroundService.execute(() -> {
409 - onHostVanished(host);
410 - onHostDetected(host);
411 - });
412 - }
413 - }
414 -
415 - }
416 -
417 - // Used to forward the flows to the local VM.
418 - private void programLocalOut(DeviceId dpid, SegmentationId segmentationId,
419 - PortNumber outPort, MacAddress sourceMac,
420 - ApplicationId appid,
421 - Objective.Operation type) {
422 - TrafficSelector selector = DefaultTrafficSelector.builder()
423 - .matchTunnelId(Long.parseLong(segmentationId.toString()))
424 - .matchEthDst(sourceMac).build();
425 - TrafficTreatment treatment = DefaultTrafficTreatment.builder()
426 - .setOutput(outPort).build();
427 - ForwardingObjective.Builder objective = DefaultForwardingObjective
428 - .builder().withTreatment(treatment).withSelector(selector)
429 - .fromApp(appId).withFlag(Flag.SPECIFIC)
430 - .withPriority(MAC_PRIORITY);
431 - if (type.equals(Objective.Operation.ADD)) {
432 - flowServiceForward(dpid, objective.add());
433 - } else {
434 - flowServiceForward(dpid, objective.remove());
435 - }
436 -
437 - }
438 -
439 - // Used to forward the flows into the VXLAN tunnel.
440 - private void programTunnelOut(DeviceId dpid, SegmentationId segmentationId,
441 - PortNumber tunnelOutPort, MacAddress dstMac,
442 - ApplicationId appid,
443 - Objective.Operation type) {
444 - TrafficSelector selector = DefaultTrafficSelector.builder()
445 - .matchEthDst(dstMac).add(Criteria.matchTunnelId(Long
446 - .parseLong(segmentationId.toString())))
447 - .build();
448 - TrafficTreatment treatment = DefaultTrafficTreatment.builder()
449 -
450 - .setOutput(tunnelOutPort).build();
451 - ForwardingObjective.Builder objective = DefaultForwardingObjective
452 - .builder().withTreatment(treatment).withSelector(selector)
453 - .fromApp(appId).withFlag(Flag.SPECIFIC)
454 - .withPriority(MAC_PRIORITY);
455 - if (type.equals(Objective.Operation.ADD)) {
456 - flowServiceForward(dpid, objective.add());
457 - } else {
458 - flowServiceForward(dpid, objective.remove());
459 - }
460 -
461 - }
462 -
463 - // Used to forward multicast flows to remote VMs of the same tenant via
464 - // VXLAN tunnel.
465 - private void programTunnelFloodOut(DeviceId deviceId,
466 - SegmentationId segmentationId,
467 - PortNumber ofPortOut,
468 - List<PortNumber> localVmPorts,
469 - ApplicationId appid,
470 - Objective.Operation type) {
471 - TrafficSelector selector = DefaultTrafficSelector.builder()
472 - .matchInPort(ofPortOut)
473 -
474 - .add(Criteria.matchTunnelId(Long.parseLong(segmentationId
475 - .toString()))).matchEthDst(MacAddress.BROADCAST)
476 - .build();
477 - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
478 -
479 - for (PortNumber outPort : localVmPorts) {
480 - treatment.setOutput(outPort);
481 - }
482 -
483 - ForwardingObjective.Builder objective = DefaultForwardingObjective
484 - .builder().withTreatment(treatment.build())
485 - .withSelector(selector).fromApp(appId).makePermanent()
486 - .withFlag(Flag.SPECIFIC).withPriority(MAC_PRIORITY);
487 - if (type.equals(Objective.Operation.ADD)) {
488 - flowServiceForward(deviceId, objective.add());
489 - } else {
490 - flowServiceForward(deviceId, objective.remove());
491 - }
492 - }
493 -
494 - // Applies default flows to mac table.
495 - private void programMacDefaultRules(DeviceId dpid, ApplicationId appid,
496 - Objective.Operation type) {
497 - TrafficSelector selector = DefaultTrafficSelector.builder().build();
498 - TrafficTreatment treatment = DefaultTrafficTreatment.builder().drop()
499 - .build();
500 - ForwardingObjective.Builder objective = DefaultForwardingObjective
501 - .builder().withTreatment(treatment).withSelector(selector)
502 - .fromApp(appId).makePermanent().withFlag(Flag.SPECIFIC)
503 - .withPriority(DEFAULT_MAC_PRIORITY);
504 - if (type.equals(Objective.Operation.ADD)) {
505 - flowServiceForward(dpid, objective.add());
506 - } else {
507 - flowServiceForward(dpid, objective.remove());
508 - }
509 - }
510 -
511 - // Used to forward the flows to the local VMs with the same tenant.
512 - private void programLocalBcastRules(DeviceId deviceId,
513 - SegmentationId segmentationId,
514 - PortNumber inPort,
515 - List<PortNumber> localVmPorts,
516 - List<PortNumber> localTunnelPorts,
517 - ApplicationId appid,
518 - Objective.Operation type) {
519 - TrafficSelector selector = DefaultTrafficSelector.builder()
520 - .matchInPort(inPort).matchEthDst(MacAddress.BROADCAST)
521 - .add(Criteria.matchTunnelId(Long
522 - .parseLong(segmentationId.toString())))
523 - .build();
524 - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
525 - for (PortNumber outPort : localVmPorts) {
526 - if (inPort != outPort) {
527 - treatment.setOutput(outPort);
528 - }
529 - }
530 - for (PortNumber outport : localTunnelPorts) {
531 - treatment.setOutput(outport);
532 - }
533 - ForwardingObjective.Builder objective = DefaultForwardingObjective
534 - .builder().withTreatment(treatment.build())
535 - .withSelector(selector).fromApp(appId).makePermanent()
536 - .withFlag(Flag.SPECIFIC).withPriority(MAC_PRIORITY);
537 - if (type.equals(Objective.Operation.ADD)) {
538 - flowServiceForward(deviceId, objective.add());
539 - } else {
540 - flowServiceForward(deviceId, objective.remove());
541 - }
542 - }
543 -
544 - // Used to apply local entry flow.
545 - private void programLocalIn(DeviceId dpid, SegmentationId segmentationId,
546 - PortNumber inPort, MacAddress srcMac,
547 - ApplicationId appid, Objective.Operation type) {
548 - TrafficSelector selector = DefaultTrafficSelector.builder()
549 - .matchInPort(inPort).matchEthSrc(srcMac).build();
550 - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
551 - treatment.add(Instructions.modTunnelId(Long.parseLong(segmentationId
552 - .toString())));
553 - ForwardingObjective.Builder objective = DefaultForwardingObjective
554 - .builder().withTreatment(treatment.build())
555 - .withSelector(selector).fromApp(appId).makePermanent()
556 - .withFlag(Flag.SPECIFIC).withPriority(PORT_PRIORITY);
557 - if (type.equals(Objective.Operation.ADD)) {
558 - flowServiceForward(dpid, objective.add());
559 - } else {
560 - flowServiceForward(dpid, objective.remove());
561 - }
562 - }
563 -
564 - // Used to forward the flows from the egress tunnel to the VM.
565 - private void programTunnelIn(DeviceId dpid, SegmentationId segmentationId,
566 - PortNumber tunnelInPort, PortNumber outPort,
567 - MacAddress sourceMac, ApplicationId appid,
568 - Objective.Operation type) {
569 - TrafficSelector selector = DefaultTrafficSelector.builder()
570 - .matchInPort(tunnelInPort).add(Criteria.matchTunnelId(Long
571 - .parseLong(segmentationId.toString())))
572 - .build();
573 - TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
574 -
575 - ForwardingObjective.Builder objective = DefaultForwardingObjective
576 - .builder().withTreatment(treatment).withSelector(selector)
577 - .fromApp(appId).makePermanent().withFlag(Flag.SPECIFIC)
578 - .withPriority(PORT_PRIORITY);
579 - if (type.equals(Objective.Operation.ADD)) {
580 - flowServiceForward(dpid, objective.add());
581 - } else {
582 - flowServiceForward(dpid, objective.remove());
583 - }
584 - }
585 -
586 - // Applies the default flows to port table.
587 - private void programPortDefaultRules(DeviceId dpid, ApplicationId appid,
588 - Objective.Operation type) {
589 - TrafficSelector selector = DefaultTrafficSelector.builder().build();
590 - TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
591 - ForwardingObjective.Builder objective = DefaultForwardingObjective
592 - .builder().withTreatment(treatment).withSelector(selector)
593 - .fromApp(appId).makePermanent().withFlag(Flag.SPECIFIC)
594 - .withPriority(DEFAULT_PORT_PRIORITY);
595 - if (type.equals(Objective.Operation.ADD)) {
596 - flowServiceForward(dpid, objective.add());
597 - } else {
598 - flowServiceForward(dpid, objective.remove());
599 - }
600 - }
601 -
602 - // Used to get channelId from the device annotations.
603 - private String getControllerIpOfSwitch(DeviceId deviceId) {
604 - Device device = deviceService.getDevice(deviceId);
605 - String url = device.annotations().value(SWITCH_CHANNEL_ID);
606 - return url.substring(0, url.lastIndexOf(":"));
607 - }
608 -
609 - private Iterable<String> getIfaceIds(String ifaceId) {
610 - VirtualPortId portId = VirtualPortId.portId(ifaceId);
611 - VirtualPort port = virtualPortService.getPort(portId);
612 - if (port == null) {
613 - return Collections.emptyList();
614 - }
615 -
616 - TenantNetwork network = tenantNetworkService
617 - .getNetwork(port.networkId());
618 - if (network == null) {
619 - return Collections.emptyList();
620 - }
621 -
622 - Collection<VirtualPort> ports = virtualPortService
623 - .getPorts(network.id());
624 - return ports.stream().map(p -> p.portId().portId())
625 - .collect(Collectors.toSet());
626 - }
627 -
628 - private List<PortNumber> getLocalPorts(DeviceId deviceId, String ifaceId) {
629 - DriverHandler handler = driverService
630 - .createHandler(getController(deviceId));
631 - BridgeConfig bridgeConfig = handler.behaviour(BridgeConfig.class);
632 - Iterable<String> ifaceIds = getIfaceIds(ifaceId);
633 - return bridgeConfig.getLocalPorts(ifaceIds);
634 - }
635 -
636 - private DeviceId getController(DeviceId deviceId) {
637 - Iterable<Device> devices = deviceService.getAvailableDevices();
638 - for (Device device : devices) {
639 - if (device.type() == Device.Type.CONTROLLER && device.id()
640 - .toString().contains(getControllerIpOfSwitch(deviceId))) {
641 - return device.id();
642 - }
643 - }
644 - log.info("Can not find controller for device : {}", deviceId);
645 - return null;
646 - }
647 -
648 - //Used to apply flowRule
649 - private void flowServiceForward(DeviceId deviceId, ForwardingObjective forwardingObjective) {
650 - Driver driver = driverService.getDriver(DRIVER_NAME);
651 - Pipeliner pipeLiner = driver.createBehaviour(new DefaultDriverData(driver, deviceId), Pipeliner.class);
652 - if (pipeLiner != null) {
653 - final PipelinerContext context = new InnerPipelineContext();
654 - pipeLiner.init(deviceId, context);
655 - pipeLiner.forward(forwardingObjective);
656 - }
657 - }
658 -
659 - // Processing context for initializing pipeline driver behaviours.
660 - private class InnerPipelineContext implements PipelinerContext {
661 - @Override
662 - public ServiceDirectory directory() {
663 - return serviceDirectory;
664 - }
665 -
666 - @Override
667 - public FlowObjectiveStore store() {
668 - return flowObjectiveStore;
669 - }
670 - }
671 -
672 -}
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.onosproject.vtn; 16 +package org.onosproject.vtn.manager;
17 17
18 import org.onosproject.net.Device; 18 import org.onosproject.net.Device;
19 import org.onosproject.net.Host; 19 import org.onosproject.net.Host;
...@@ -24,18 +24,20 @@ import org.onosproject.net.Host; ...@@ -24,18 +24,20 @@ import org.onosproject.net.Host;
24 public interface VTNService { 24 public interface VTNService {
25 25
26 /** 26 /**
27 - * Creates a vxlan tunnel and creates the ovs when a ovs controller node is detected. 27 + * Creates a vxlan tunnel and creates the ovs when a ovs controller node is
28 + * detected.
28 * 29 *
29 * @param device controller-type device 30 * @param device controller-type device
30 */ 31 */
31 - void onServerDetected(Device device); 32 + void onControllerDetected(Device device);
32 33
33 /** 34 /**
34 - * Drops a vxlan tunnel and drops the ovs when a ovs controller node is vanished. 35 + * Drops a vxlan tunnel and drops the ovs when a ovs controller node is
36 + * vanished.
35 * 37 *
36 * @param device controller-type device 38 * @param device controller-type device
37 */ 39 */
38 - void onServerVanished(Device device); 40 + void onControllerVanished(Device device);
39 41
40 /** 42 /**
41 * Applies default forwarding flows when a ovs is detected. 43 * Applies default forwarding flows when a ovs is detected.
......
1 +/*
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 + */
16 +package org.onosproject.vtn.manager.impl;
17 +
18 +import static org.slf4j.LoggerFactory.getLogger;
19 +
20 +import java.util.Collection;
21 +import java.util.HashMap;
22 +import java.util.HashSet;
23 +import java.util.Iterator;
24 +import java.util.Map;
25 +import java.util.Set;
26 +
27 +import org.apache.felix.scr.annotations.Activate;
28 +import org.apache.felix.scr.annotations.Component;
29 +import org.apache.felix.scr.annotations.Deactivate;
30 +import org.apache.felix.scr.annotations.Reference;
31 +import org.apache.felix.scr.annotations.ReferenceCardinality;
32 +import org.apache.felix.scr.annotations.Service;
33 +import org.onlab.packet.IpAddress;
34 +import org.onlab.packet.MacAddress;
35 +import org.onlab.util.KryoNamespace;
36 +import org.onosproject.core.ApplicationId;
37 +import org.onosproject.core.CoreService;
38 +import org.onosproject.mastership.MastershipService;
39 +import org.onosproject.net.Device;
40 +import org.onosproject.net.DeviceId;
41 +import org.onosproject.net.Host;
42 +import org.onosproject.net.Port;
43 +import org.onosproject.net.PortNumber;
44 +import org.onosproject.net.behaviour.BridgeConfig;
45 +import org.onosproject.net.behaviour.BridgeDescription;
46 +import org.onosproject.net.config.NetworkConfigService;
47 +import org.onosproject.net.config.basics.BasicDeviceConfig;
48 +import org.onosproject.net.device.DeviceEvent;
49 +import org.onosproject.net.device.DeviceListener;
50 +import org.onosproject.net.device.DeviceService;
51 +import org.onosproject.net.driver.DriverHandler;
52 +import org.onosproject.net.driver.DriverService;
53 +import org.onosproject.net.flowobjective.Objective;
54 +import org.onosproject.net.host.HostEvent;
55 +import org.onosproject.net.host.HostListener;
56 +import org.onosproject.net.host.HostService;
57 +import org.onosproject.store.serializers.KryoNamespaces;
58 +import org.onosproject.store.service.ConsistentMap;
59 +import org.onosproject.store.service.EventuallyConsistentMap;
60 +import org.onosproject.store.service.LogicalClockService;
61 +import org.onosproject.store.service.Serializer;
62 +import org.onosproject.store.service.StorageService;
63 +import org.onosproject.vtn.manager.VTNService;
64 +import org.onosproject.vtn.table.ClassifierService;
65 +import org.onosproject.vtn.table.L2ForwardService;
66 +import org.onosproject.vtn.table.impl.ClassifierServiceImpl;
67 +import org.onosproject.vtn.table.impl.L2ForwardServiceImpl;
68 +import org.onosproject.vtn.util.DataPathIdGenerator;
69 +import org.onosproject.vtn.util.VtnConfig;
70 +import org.onosproject.vtn.util.VtnData;
71 +import org.onosproject.vtnrsc.SegmentationId;
72 +import org.onosproject.vtnrsc.SubnetId;
73 +import org.onosproject.vtnrsc.TenantId;
74 +import org.onosproject.vtnrsc.TenantNetwork;
75 +import org.onosproject.vtnrsc.TenantNetworkId;
76 +import org.onosproject.vtnrsc.VirtualPort;
77 +import org.onosproject.vtnrsc.VirtualPortId;
78 +import org.onosproject.vtnrsc.tenantnetwork.TenantNetworkService;
79 +import org.onosproject.vtnrsc.virtualport.VirtualPortService;
80 +import org.slf4j.Logger;
81 +
82 +import com.google.common.collect.Sets;
83 +
84 +/**
85 + * Provides implementation of VTNService.
86 + */
87 +@Component(immediate = true)
88 +@Service
89 +public class VTNManager implements VTNService {
90 + private final Logger log = getLogger(getClass());
91 + private static final String APP_ID = "org.onosproject.app.vtn";
92 +
93 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
94 + protected NetworkConfigService configService;
95 +
96 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
97 + protected DeviceService deviceService;
98 +
99 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
100 + protected HostService hostService;
101 +
102 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
103 + protected CoreService coreService;
104 +
105 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
106 + protected StorageService storageService;
107 +
108 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
109 + protected TenantNetworkService tenantNetworkService;
110 +
111 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
112 + protected VirtualPortService virtualPortService;
113 +
114 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
115 + protected DriverService driverService;
116 +
117 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
118 + protected LogicalClockService clockService;
119 +
120 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
121 + protected MastershipService mastershipService;
122 +
123 + private ApplicationId appId;
124 + private ClassifierService classifierService;
125 + private L2ForwardService l2ForwardService;
126 +
127 + private final HostListener hostListener = new InnerHostListener();
128 + private final DeviceListener deviceListener = new InnerDeviceListener();
129 +
130 + private static final String IFACEID = "ifaceid";
131 + private static final String CONTROLLER_IP_KEY = "ipaddress";
132 + public static final String DRIVER_NAME = "onosfw";
133 + private static final String EX_PORT_NAME = "eth0";
134 + private static final String SWITCHES_OF_CONTROLLER = "switchesOfController";
135 + private static final String SWITCH_OF_LOCAL_HOST_PORTS = "switchOfLocalHostPorts";
136 +
137 + private EventuallyConsistentMap<IpAddress, Boolean> switchesOfController;
138 + private ConsistentMap<DeviceId, NetworkOfLocalHostPorts> switchOfLocalHostPorts;
139 +
140 + @Activate
141 + public void activate() {
142 + appId = coreService.registerApplication(APP_ID);
143 + classifierService = new ClassifierServiceImpl(appId);
144 + l2ForwardService = new L2ForwardServiceImpl(appId);
145 +
146 + deviceService.addListener(deviceListener);
147 + hostService.addListener(hostListener);
148 +
149 + KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
150 + .register(KryoNamespaces.API)
151 + .register(NetworkOfLocalHostPorts.class)
152 + .register(TenantNetworkId.class)
153 + .register(Host.class)
154 + .register(TenantNetwork.class)
155 + .register(TenantId.class)
156 + .register(SubnetId.class);
157 +
158 + switchesOfController = storageService
159 + .<IpAddress, Boolean>eventuallyConsistentMapBuilder()
160 + .withName(SWITCHES_OF_CONTROLLER).withSerializer(serializer)
161 + .withTimestampProvider((k, v) -> clockService.getTimestamp())
162 + .build();
163 +
164 + switchOfLocalHostPorts = storageService
165 + .<DeviceId, NetworkOfLocalHostPorts>consistentMapBuilder()
166 + .withName(SWITCH_OF_LOCAL_HOST_PORTS)
167 + .withSerializer(Serializer.using(serializer.build()))
168 + .build();
169 +
170 + log.info("Started");
171 + }
172 +
173 + @Deactivate
174 + public void deactivate() {
175 + deviceService.removeListener(deviceListener);
176 + hostService.removeListener(hostListener);
177 + log.info("Stopped");
178 + }
179 +
180 + @Override
181 + public void onControllerDetected(Device controllerDevice) {
182 + if (controllerDevice == null) {
183 + log.error("The controller device is null");
184 + return;
185 + }
186 + String localIpAddress = controllerDevice.annotations()
187 + .value(CONTROLLER_IP_KEY);
188 + IpAddress localIp = IpAddress.valueOf(localIpAddress);
189 + DeviceId controllerDeviceId = controllerDevice.id();
190 + DriverHandler handler = driverService.createHandler(controllerDeviceId);
191 + if (mastershipService.isLocalMaster(controllerDeviceId)) {
192 + // Get DataPathIdGenerator
193 + String ipaddress = controllerDevice.annotations().value("ipaddress");
194 + DataPathIdGenerator dpidGenerator = DataPathIdGenerator.builder()
195 + .addIpAddress(ipaddress).build();
196 + DeviceId deviceId = dpidGenerator.getDeviceId();
197 + String dpid = dpidGenerator.getDpId();
198 + // Inject pipeline driver name
199 + BasicDeviceConfig config = configService.addConfig(deviceId,
200 + BasicDeviceConfig.class);
201 + config.driver(DRIVER_NAME);
202 + configService.applyConfig(deviceId, BasicDeviceConfig.class, config.node());
203 + // Add Bridge
204 + VtnConfig.applyBridgeConfig(handler, dpid, EX_PORT_NAME);
205 + log.info("A new ovs is created in node {}", localIp.toString());
206 + switchesOfController.put(localIp, true);
207 + }
208 + // Create tunnel in br-int on all controllers
209 + programTunnelConfig(controllerDeviceId, localIp, handler);
210 + }
211 +
212 + @Override
213 + public void onControllerVanished(Device controllerDevice) {
214 + if (controllerDevice == null) {
215 + log.error("The device is null");
216 + return;
217 + }
218 + String dstIp = controllerDevice.annotations().value(CONTROLLER_IP_KEY);
219 + IpAddress dstIpAddress = IpAddress.valueOf(dstIp);
220 + DeviceId controllerDeviceId = controllerDevice.id();
221 + if (mastershipService.isLocalMaster(controllerDeviceId)) {
222 + switchesOfController.remove(dstIpAddress);
223 + }
224 + // remove tunnel in br-int on other controllers
225 + programTunnelConfig(controllerDeviceId, dstIpAddress, null);
226 + }
227 +
228 + @Override
229 + public void onOvsDetected(Device device) {
230 + // Create tunnel out flow rules
231 + applyTunnelOut(device, Objective.Operation.ADD);
232 + }
233 +
234 + @Override
235 + public void onOvsVanished(Device device) {
236 + // Remove Tunnel out flow rules
237 + applyTunnelOut(device, Objective.Operation.REMOVE);
238 + }
239 +
240 + @Override
241 + public void onHostDetected(Host host) {
242 + // apply L2 openflow rules
243 + applyHostMonitoredL2Rules(host, Objective.Operation.ADD);
244 + }
245 +
246 + @Override
247 + public void onHostVanished(Host host) {
248 + // apply L2 openflow rules
249 + applyHostMonitoredL2Rules(host, Objective.Operation.REMOVE);
250 + }
251 +
252 + private void programTunnelConfig(DeviceId localDeviceId, IpAddress localIp,
253 + DriverHandler localHandler) {
254 + Iterable<Device> devices = deviceService.getAvailableDevices();
255 + Sets.newHashSet(devices).stream()
256 + .filter(d -> Device.Type.CONTROLLER == d.type())
257 + .filter(d -> !localDeviceId.equals(d.id())).forEach(d -> {
258 + DriverHandler tunHandler = driverService
259 + .createHandler(d.id());
260 + String remoteIpAddress = d.annotations()
261 + .value(CONTROLLER_IP_KEY);
262 + IpAddress remoteIp = IpAddress.valueOf(remoteIpAddress);
263 + if (remoteIp.toString()
264 + .equalsIgnoreCase(localIp.toString())) {
265 + log.error("The localIp and remoteIp are the same");
266 + return;
267 + }
268 + if (localHandler != null) {
269 + // Create tunnel in br-int on local controller
270 + if (mastershipService.isLocalMaster(localDeviceId)) {
271 + VtnConfig.applyTunnelConfig(localHandler, localIp, remoteIp);
272 + log.info("Add tunnel between {} and {}", localIp,
273 + remoteIp);
274 + }
275 + // Create tunnel in br-int on other controllers
276 + if (mastershipService.isLocalMaster(d.id())) {
277 + VtnConfig.applyTunnelConfig(tunHandler, remoteIp,
278 + localIp);
279 + log.info("Add tunnel between {} and {}", remoteIp,
280 + localIp);
281 + }
282 + } else {
283 + // remove tunnel in br-int on other controllers
284 + if (mastershipService.isLocalMaster(d.id())) {
285 + VtnConfig.removeTunnelConfig(tunHandler, remoteIp,
286 + localIp);
287 + log.info("Remove tunnel between {} and {}", remoteIp,
288 + localIp);
289 + }
290 + }
291 + });
292 + }
293 +
294 + private void applyTunnelOut(Device device, Objective.Operation type) {
295 + if (device == null) {
296 + log.error("The device is null");
297 + return;
298 + }
299 + if (!mastershipService.isLocalMaster(device.id())) {
300 + return;
301 + }
302 + String controllerIp = VtnData.getControllerIpOfSwitch(device);
303 + if (controllerIp == null) {
304 + log.error("Can't find controller of device: {}",
305 + device.id().toString());
306 + return;
307 + }
308 + IpAddress ipAddress = IpAddress.valueOf(controllerIp);
309 + if (!switchesOfController.containsKey(ipAddress)) {
310 + log.error("Can't find controller of device: {}",
311 + device.id().toString());
312 + return;
313 + }
314 + if (type == Objective.Operation.ADD) {
315 + switchOfLocalHostPorts.put(device.id(), new NetworkOfLocalHostPorts());
316 + } else if (type == Objective.Operation.REMOVE) {
317 + switchOfLocalHostPorts.remove(device.id());
318 + }
319 + Iterable<Device> devices = deviceService.getAvailableDevices();
320 + DeviceId localControllerId = VtnData.getControllerId(device, devices);
321 + DriverHandler handler = driverService.createHandler(localControllerId);
322 + Set<PortNumber> ports = VtnConfig.getPortNumbers(handler);
323 + Iterable<Host> allHosts = hostService.getHosts();
324 + if (allHosts != null) {
325 + Sets.newHashSet(allHosts).stream().forEach(host -> {
326 + MacAddress hostMac = host.mac();
327 + String ifaceId = host.annotations().value(IFACEID);
328 + if (ifaceId == null) {
329 + log.error("The ifaceId of Host is null");
330 + return;
331 + }
332 + VirtualPortId virtualPortId = VirtualPortId.portId(ifaceId);
333 + VirtualPort virtualPort = virtualPortService
334 + .getPort(virtualPortId);
335 + TenantNetwork network = tenantNetworkService
336 + .getNetwork(virtualPort.networkId());
337 + SegmentationId segmentationId = network.segmentationId();
338 + DeviceId remoteDeviceId = host.location().deviceId();
339 + Device remoteDevice = deviceService.getDevice(remoteDeviceId);
340 + String remoteControllerIp = VtnData
341 + .getControllerIpOfSwitch(remoteDevice);
342 + if (remoteControllerIp == null) {
343 + log.error("Can't find remote controller of device: {}",
344 + remoteDeviceId.toString());
345 + return;
346 + }
347 + IpAddress remoteIpAddress = IpAddress
348 + .valueOf(remoteControllerIp);
349 + String tunnelName = "vxlan-" + remoteIpAddress.toString();
350 + ports.stream()
351 + .filter(p -> p.name().equalsIgnoreCase(tunnelName))
352 + .forEach(p -> {
353 + l2ForwardService
354 + .programTunnelOut(device.id(), segmentationId, p,
355 + hostMac, type);
356 + });
357 + });
358 + }
359 + }
360 +
361 + private void applyHostMonitoredL2Rules(Host host, Objective.Operation type) {
362 + DeviceId deviceId = host.location().deviceId();
363 + if (!mastershipService.isLocalMaster(deviceId)) {
364 + return;
365 + }
366 + String ifaceId = host.annotations().value(IFACEID);
367 + if (ifaceId == null) {
368 + log.error("The ifaceId of Host is null");
369 + return;
370 + }
371 + VirtualPortId virtualPortId = VirtualPortId.portId(ifaceId);
372 + VirtualPort virtualPort = virtualPortService.getPort(virtualPortId);
373 + if (virtualPort == null) {
374 + log.error("The virtualPort of host is null");
375 + return;
376 + }
377 +
378 + Iterable<Device> devices = deviceService.getAvailableDevices();
379 + PortNumber inPort = host.location().port();
380 + MacAddress mac = host.mac();
381 + Device device = deviceService.getDevice(deviceId);
382 + String controllerIp = VtnData.getControllerIpOfSwitch(device);
383 + IpAddress ipAddress = IpAddress.valueOf(controllerIp);
384 + TenantNetwork network = tenantNetworkService.getNetwork(virtualPort.networkId());
385 + if (network == null) {
386 + log.error("Can't find network of the host");
387 + return;
388 + }
389 + SegmentationId segmentationId = network.segmentationId();
390 + // Get all the tunnel PortNumber in the current node
391 + Iterable<Port> ports = deviceService.getPorts(deviceId);
392 + Collection<PortNumber> localTunnelPorts = VtnData.getLocalTunnelPorts(ports);
393 + // Get all the local vm's PortNumber in the current node
394 + Map<TenantNetworkId, Set<PortNumber>> localHostPorts = switchOfLocalHostPorts
395 + .get(deviceId).value().getNetworkOfLocalHostPorts();
396 + Set<PortNumber> networkOflocalHostPorts = localHostPorts.get(network.id());
397 +
398 + l2ForwardService.programLocalBcastRules(deviceId, segmentationId,
399 + inPort, networkOflocalHostPorts,
400 + localTunnelPorts,
401 + type);
402 +
403 + l2ForwardService.programLocalOut(deviceId, segmentationId, inPort, mac,
404 + type);
405 +
406 + if (type == Objective.Operation.ADD) {
407 + if (networkOflocalHostPorts == null) {
408 + networkOflocalHostPorts = new HashSet<PortNumber>();
409 + localHostPorts.putIfAbsent(network.id(), networkOflocalHostPorts);
410 + }
411 + networkOflocalHostPorts.add(inPort);
412 + classifierService.programTunnelIn(deviceId, segmentationId,
413 + localTunnelPorts,
414 + type);
415 + } else if (type == Objective.Operation.REMOVE) {
416 + networkOflocalHostPorts.remove(inPort);
417 + if (networkOflocalHostPorts.isEmpty()) {
418 + classifierService.programTunnelIn(deviceId, segmentationId,
419 + localTunnelPorts,
420 + Objective.Operation.REMOVE);
421 + switchOfLocalHostPorts.get(deviceId).value().getNetworkOfLocalHostPorts()
422 + .remove(virtualPort.networkId());
423 + }
424 + }
425 +
426 + l2ForwardService.programTunnelBcastRules(deviceId, segmentationId,
427 + networkOflocalHostPorts,
428 + localTunnelPorts,
429 + type);
430 +
431 + programTunnelOuts(devices, ipAddress, segmentationId, mac,
432 + type);
433 +
434 + classifierService.programLocalIn(deviceId, segmentationId, inPort, mac,
435 + appId, type);
436 + }
437 +
438 + private void programTunnelOuts(Iterable<Device> devices,
439 + IpAddress ipAddress,
440 + SegmentationId segmentationId,
441 + MacAddress dstMac,
442 + Objective.Operation type) {
443 + String tunnelName = "vxlan-" + ipAddress.toString();
444 + Sets.newHashSet(devices).stream()
445 + .filter(d -> d.type() == Device.Type.CONTROLLER).forEach(d -> {
446 + DriverHandler handler = driverService.createHandler(d.id());
447 + BridgeConfig bridgeConfig = handler
448 + .behaviour(BridgeConfig.class);
449 + Collection<BridgeDescription> bridgeDescriptions = bridgeConfig
450 + .getBridges();
451 + Set<PortNumber> ports = bridgeConfig.getPortNumbers();
452 + Iterator<BridgeDescription> it = bridgeDescriptions
453 + .iterator();
454 + if (it.hasNext()) {
455 + BridgeDescription sw = it.next();
456 + ports.stream()
457 + .filter(p -> p.name()
458 + .equalsIgnoreCase(tunnelName))
459 + .forEach(p -> {
460 + l2ForwardService.programTunnelOut(sw.deviceId(),
461 + segmentationId, p,
462 + dstMac, type);
463 + });
464 + }
465 + });
466 + }
467 +
468 + private class InnerDeviceListener implements DeviceListener {
469 +
470 + @Override
471 + public void event(DeviceEvent event) {
472 + Device device = event.subject();
473 + if (Device.Type.CONTROLLER == device.type()) {
474 + if (DeviceEvent.Type.DEVICE_ADDED == event.type()) {
475 + onControllerDetected(device);
476 + }
477 + if (DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED == event.type()) {
478 + if (deviceService.isAvailable(device.id())) {
479 + onControllerDetected(device);
480 + } else {
481 + onControllerVanished(device);
482 + }
483 + }
484 + } else if (Device.Type.SWITCH == device.type()) {
485 + if (DeviceEvent.Type.DEVICE_ADDED == event.type()) {
486 + onOvsDetected(device);
487 + }
488 + if (DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED == event.type()) {
489 + if (deviceService.isAvailable(device.id())) {
490 + onOvsDetected(device);
491 + } else {
492 + onOvsVanished(device);
493 + }
494 + }
495 + } else {
496 + log.info("Do nothing for this device type");
497 + }
498 + }
499 + }
500 +
501 + private class InnerHostListener implements HostListener {
502 +
503 + @Override
504 + public void event(HostEvent event) {
505 + Host host = event.subject();
506 + if (HostEvent.Type.HOST_ADDED == event.type()) {
507 + onHostDetected(host);
508 + } else if (HostEvent.Type.HOST_REMOVED == event.type()) {
509 + onHostVanished(host);
510 + } else if (HostEvent.Type.HOST_UPDATED == event.type()) {
511 + onHostVanished(host);
512 + onHostDetected(host);
513 + }
514 + }
515 +
516 + }
517 +
518 + // Local Host Ports of Network.
519 + private class NetworkOfLocalHostPorts {
520 + private final Map<TenantNetworkId, Set<PortNumber>> networkOfLocalHostPorts =
521 + new HashMap<TenantNetworkId, Set<PortNumber>>();
522 +
523 + public Map<TenantNetworkId, Set<PortNumber>> getNetworkOfLocalHostPorts() {
524 + return networkOfLocalHostPorts;
525 + }
526 + }
527 +
528 +}
...@@ -17,4 +17,4 @@ ...@@ -17,4 +17,4 @@
17 /** 17 /**
18 * VTN application that applies configuration and flows to the device. 18 * VTN application that applies configuration and flows to the device.
19 */ 19 */
20 -package org.onosproject.vtn.impl; 20 +package org.onosproject.vtn.manager.impl;
......
...@@ -17,4 +17,4 @@ ...@@ -17,4 +17,4 @@
17 /** 17 /**
18 * VTN application that applies configuration and flows to the device. 18 * VTN application that applies configuration and flows to the device.
19 */ 19 */
20 -package org.onosproject.vtn; 20 +package org.onosproject.vtn.manager;
......
1 +/*
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 + */
16 +package org.onosproject.vtn.table;
17 +
18 +import org.onlab.packet.MacAddress;
19 +import org.onosproject.core.ApplicationId;
20 +import org.onosproject.net.DeviceId;
21 +import org.onosproject.net.PortNumber;
22 +import org.onosproject.net.flowobjective.Objective;
23 +import org.onosproject.vtnrsc.SegmentationId;
24 +
25 +/**
26 + * Applies classifier flows to the device.
27 + */
28 +public interface ClassifierService {
29 +
30 + /**
31 + * The port rule that message from host matches Table(0) Match: host mac and
32 + * ingress port Action: set vnid and go to table(50).
33 + *
34 + * @param deviceId Device Id
35 + * @param segmentationId the vnid of the host belong to
36 + * @param inPort the ingress port of the host
37 + * @param srcMac the mac of the host
38 + * @param appId the application ID of the vtn
39 + * @param type the operation of the flow
40 + */
41 + void programLocalIn(DeviceId deviceId, SegmentationId segmentationId,
42 + PortNumber inPort, MacAddress srcMac,
43 + ApplicationId appId, Objective.Operation type);
44 +
45 + /**
46 + * The port rule that message from tunnel Table(0) Match: tunnel port and
47 + * vnid Action: go to table(50).
48 + *
49 + * @param deviceId Device Id
50 + * @param segmentationId the vnid of the host belong to
51 + * @param localTunnelPorts the tunnel pors of the device
52 + * @param type the operation of the flow
53 + */
54 + void programTunnelIn(DeviceId deviceId, SegmentationId segmentationId,
55 + Iterable<PortNumber> localTunnelPorts,
56 + Objective.Operation type);
57 +
58 +}
1 +/*
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 + */
16 +package org.onosproject.vtn.table;
17 +
18 +import org.onlab.packet.MacAddress;
19 +import org.onosproject.net.DeviceId;
20 +import org.onosproject.net.PortNumber;
21 +import org.onosproject.net.flowobjective.Objective;
22 +import org.onosproject.vtnrsc.SegmentationId;
23 +
24 +/**
25 + * Applies L2 flows to the device.
26 + */
27 +public interface L2ForwardService {
28 +
29 + /**
30 + * The local broadcast rule that message matches Table(50) Match: broadcast
31 + * mac and vnid Action: output port.
32 + *
33 + * @param deviceId Device Id
34 + * @param segmentationId the vnid of the host belong to
35 + * @param inPort the ingress port of the host
36 + * @param localVmPorts the local ports of the network which connect host
37 + * @param localTunnelPorts the tunnel pors of the device
38 + * @param type the operation of the flow
39 + */
40 + void programLocalBcastRules(DeviceId deviceId,
41 + SegmentationId segmentationId,
42 + PortNumber inPort,
43 + Iterable<PortNumber> localVmPorts,
44 + Iterable<PortNumber> localTunnelPorts,
45 + Objective.Operation type);
46 +
47 + /**
48 + * The tunnel broadcast rule that message matches Table(50) Match: broadcast
49 + * mac and vnid Action: output port.
50 + *
51 + * @param deviceId Device Id
52 + * @param segmentationId the vnid of the host belong to
53 + * @param localVmPorts the local ports of the network which connect host
54 + * @param localTunnelPorts the tunnel pors of the device
55 + * @param type the operation of the flow
56 + */
57 + void programTunnelBcastRules(DeviceId deviceId,
58 + SegmentationId segmentationId,
59 + Iterable<PortNumber> localVmPorts,
60 + Iterable<PortNumber> localTunnelPorts,
61 + Objective.Operation type);
62 +
63 + /**
64 + * The local out rule that message matches. Table(50) Match: local host mac
65 + * and vnid Action: output local host port.
66 + *
67 + * @param deviceId Device Id
68 + * @param segmentationId the vnid of the host belong to
69 + * @param outPort the ingress port of the host
70 + * @param sourceMac the mac of the host
71 + * @param type the operation of the flow
72 + */
73 + void programLocalOut(DeviceId deviceId, SegmentationId segmentationId,
74 + PortNumber outPort, MacAddress sourceMac,
75 + Objective.Operation type);
76 +
77 + /**
78 + * The tunnel out rule that message matches. Table(50) Match: host mac and
79 + * vnid Action: output tunnel port.
80 + *
81 + * @param deviceId Device Id
82 + * @param segmentationId the vnid of the host belong to
83 + * @param tunnelOutPort the port of the tunnel
84 + * @param dstMac the mac of the host
85 + * @param type the operation of the flow
86 + */
87 + void programTunnelOut(DeviceId deviceId, SegmentationId segmentationId,
88 + PortNumber tunnelOutPort, MacAddress dstMac,
89 + Objective.Operation type);
90 +
91 +}
1 +/*
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 + */
16 +package org.onosproject.vtn.table.impl;
17 +
18 +import static com.google.common.base.Preconditions.checkNotNull;
19 +import static org.slf4j.LoggerFactory.getLogger;
20 +
21 +import org.onlab.osgi.DefaultServiceDirectory;
22 +import org.onlab.osgi.ServiceDirectory;
23 +import org.onlab.packet.MacAddress;
24 +import org.onosproject.core.ApplicationId;
25 +import org.onosproject.net.DeviceId;
26 +import org.onosproject.net.PortNumber;
27 +import org.onosproject.net.flow.DefaultTrafficSelector;
28 +import org.onosproject.net.flow.DefaultTrafficTreatment;
29 +import org.onosproject.net.flow.TrafficSelector;
30 +import org.onosproject.net.flow.TrafficTreatment;
31 +import org.onosproject.net.flow.criteria.Criteria;
32 +import org.onosproject.net.flow.instructions.Instructions;
33 +import org.onosproject.net.flowobjective.DefaultForwardingObjective;
34 +import org.onosproject.net.flowobjective.FlowObjectiveService;
35 +import org.onosproject.net.flowobjective.ForwardingObjective;
36 +import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
37 +import org.onosproject.net.flowobjective.Objective;
38 +import org.onosproject.vtn.table.ClassifierService;
39 +import org.onosproject.vtnrsc.SegmentationId;
40 +import org.slf4j.Logger;
41 +
42 +import com.google.common.collect.Sets;
43 +
44 +/**
45 + * Provides implementation of ClassifierService.
46 + */
47 +public class ClassifierServiceImpl implements ClassifierService {
48 + private final Logger log = getLogger(getClass());
49 +
50 + private static final int L2_CLAFFIFIER_PRIORITY = 50000;
51 +
52 + private final FlowObjectiveService flowObjectiveService;
53 + private final ApplicationId appId;
54 +
55 + /**
56 + * Constructor.
57 + *
58 + * @param appId the application id of vtn
59 + */
60 + public ClassifierServiceImpl(ApplicationId appId) {
61 + this.appId = checkNotNull(appId, "ApplicationId can not be null");
62 + ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
63 + this.flowObjectiveService = serviceDirectory.get(FlowObjectiveService.class);
64 + }
65 +
66 + @Override
67 + public void programLocalIn(DeviceId deviceId,
68 + SegmentationId segmentationId, PortNumber inPort,
69 + MacAddress srcMac, ApplicationId appid,
70 + Objective.Operation type) {
71 + TrafficSelector selector = DefaultTrafficSelector.builder()
72 + .matchInPort(inPort).matchEthSrc(srcMac).build();
73 + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
74 + treatment.add(Instructions
75 + .modTunnelId(Long.parseLong(segmentationId.toString())));
76 + ForwardingObjective.Builder objective = DefaultForwardingObjective
77 + .builder().withTreatment(treatment.build())
78 + .withSelector(selector).fromApp(appId).makePermanent()
79 + .withFlag(Flag.SPECIFIC).withPriority(L2_CLAFFIFIER_PRIORITY);
80 + if (type.equals(Objective.Operation.ADD)) {
81 + log.debug("programLocalIn-->ADD");
82 + flowObjectiveService.forward(deviceId, objective.add());
83 + } else {
84 + log.debug("programLocalIn-->REMOVE");
85 + flowObjectiveService.forward(deviceId, objective.remove());
86 + }
87 + }
88 +
89 + @Override
90 + public void programTunnelIn(DeviceId deviceId,
91 + SegmentationId segmentationId,
92 + Iterable<PortNumber> localTunnelPorts,
93 + Objective.Operation type) {
94 + if (localTunnelPorts == null) {
95 + log.info("No tunnel port in device");
96 + return;
97 + }
98 + Sets.newHashSet(localTunnelPorts).stream().forEach(tp -> {
99 + TrafficSelector selector = DefaultTrafficSelector.builder()
100 + .matchInPort(tp).add(Criteria.matchTunnelId(Long
101 + .parseLong(segmentationId.toString())))
102 + .build();
103 +
104 + TrafficTreatment treatment = DefaultTrafficTreatment.builder()
105 + .build();
106 + ForwardingObjective.Builder objective = DefaultForwardingObjective
107 + .builder().withTreatment(treatment).withSelector(selector)
108 + .fromApp(appId).makePermanent().withFlag(Flag.SPECIFIC)
109 + .withPriority(L2_CLAFFIFIER_PRIORITY);
110 + if (type.equals(Objective.Operation.ADD)) {
111 + log.debug("programTunnelIn-->ADD");
112 + flowObjectiveService.forward(deviceId, objective.add());
113 + } else {
114 + log.debug("programTunnelIn-->REMOVE");
115 + flowObjectiveService.forward(deviceId, objective.remove());
116 + }
117 + });
118 + }
119 +
120 +}
1 +/*
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 + */
16 +package org.onosproject.vtn.table.impl;
17 +
18 +import static com.google.common.base.Preconditions.checkNotNull;
19 +import static org.slf4j.LoggerFactory.getLogger;
20 +
21 +import org.onlab.osgi.DefaultServiceDirectory;
22 +import org.onlab.osgi.ServiceDirectory;
23 +import org.onlab.packet.MacAddress;
24 +import org.onosproject.core.ApplicationId;
25 +import org.onosproject.net.DeviceId;
26 +import org.onosproject.net.PortNumber;
27 +import org.onosproject.net.flow.DefaultTrafficSelector;
28 +import org.onosproject.net.flow.DefaultTrafficTreatment;
29 +import org.onosproject.net.flow.TrafficSelector;
30 +import org.onosproject.net.flow.TrafficTreatment;
31 +import org.onosproject.net.flow.criteria.Criteria;
32 +import org.onosproject.net.flowobjective.DefaultForwardingObjective;
33 +import org.onosproject.net.flowobjective.FlowObjectiveService;
34 +import org.onosproject.net.flowobjective.ForwardingObjective;
35 +import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
36 +import org.onosproject.net.flowobjective.Objective;
37 +import org.onosproject.vtn.table.L2ForwardService;
38 +import org.onosproject.vtnrsc.SegmentationId;
39 +import org.slf4j.Logger;
40 +
41 +import com.google.common.collect.Sets;
42 +
43 +/**
44 + * Provides implementation of L2ForwardService.
45 + */
46 +public final class L2ForwardServiceImpl implements L2ForwardService {
47 + private final Logger log = getLogger(getClass());
48 +
49 + private static final int MAC_PRIORITY = 0xffff;
50 +
51 + private final FlowObjectiveService flowObjectiveService;
52 + private final ApplicationId appId;
53 +
54 + /**
55 + * Constructor.
56 + *
57 + * @param appId the application id of vtn
58 + */
59 + public L2ForwardServiceImpl(ApplicationId appId) {
60 + this.appId = checkNotNull(appId, "ApplicationId can not be null");
61 + ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
62 + this.flowObjectiveService = serviceDirectory.get(FlowObjectiveService.class);
63 + }
64 +
65 + @Override
66 + public void programLocalBcastRules(DeviceId deviceId,
67 + SegmentationId segmentationId,
68 + PortNumber inPort,
69 + Iterable<PortNumber> localVmPorts,
70 + Iterable<PortNumber> localTunnelPorts,
71 + Objective.Operation type) {
72 + if (localVmPorts == null || localTunnelPorts == null) {
73 + log.info("No other host port and tunnel in the device");
74 + return;
75 + }
76 + Sets.newHashSet(localVmPorts).stream().forEach(lp -> {
77 + TrafficSelector selector = DefaultTrafficSelector.builder()
78 + .matchInPort(lp).matchEthDst(MacAddress.BROADCAST)
79 + .add(Criteria.matchTunnelId(Long
80 + .parseLong(segmentationId.toString())))
81 + .build();
82 + TrafficTreatment.Builder treatment = DefaultTrafficTreatment
83 + .builder();
84 + boolean flag = false;
85 + for (PortNumber outPort : localVmPorts) {
86 + flag = true;
87 + if (outPort != lp) {
88 + treatment.setOutput(outPort);
89 + }
90 + }
91 + if (type.equals(Objective.Operation.REMOVE) && inPort == lp) {
92 + flag = false;
93 + }
94 + for (PortNumber outport : localTunnelPorts) {
95 + treatment.setOutput(outport);
96 + }
97 + ForwardingObjective.Builder objective = DefaultForwardingObjective
98 + .builder().withTreatment(treatment.build())
99 + .withSelector(selector).fromApp(appId).makePermanent()
100 + .withFlag(Flag.SPECIFIC).withPriority(MAC_PRIORITY);
101 + if (flag) {
102 + flowObjectiveService.forward(deviceId, objective.add());
103 + } else {
104 + flowObjectiveService.forward(deviceId, objective.remove());
105 + }
106 + });
107 + }
108 +
109 + @Override
110 + public void programTunnelBcastRules(DeviceId deviceId,
111 + SegmentationId segmentationId,
112 + Iterable<PortNumber> localVmPorts,
113 + Iterable<PortNumber> localTunnelPorts,
114 + Objective.Operation type) {
115 + if (localVmPorts == null || localTunnelPorts == null) {
116 + log.info("No other host port or tunnel ports in the device");
117 + return;
118 + }
119 + Sets.newHashSet(localTunnelPorts).stream().forEach(tp -> {
120 + TrafficSelector selector = DefaultTrafficSelector.builder()
121 + .matchInPort(tp)
122 + .add(Criteria.matchTunnelId(Long
123 + .parseLong(segmentationId.toString())))
124 + .matchEthDst(MacAddress.BROADCAST).build();
125 + TrafficTreatment.Builder treatment = DefaultTrafficTreatment
126 + .builder();
127 +
128 + for (PortNumber outPort : localVmPorts) {
129 + treatment.setOutput(outPort);
130 + }
131 +
132 + ForwardingObjective.Builder objective = DefaultForwardingObjective
133 + .builder().withTreatment(treatment.build())
134 + .withSelector(selector).fromApp(appId).makePermanent()
135 + .withFlag(Flag.SPECIFIC).withPriority(MAC_PRIORITY);
136 + if (type.equals(Objective.Operation.ADD)) {
137 + if (Sets.newHashSet(localVmPorts).size() == 0) {
138 + flowObjectiveService.forward(deviceId, objective.remove());
139 + } else {
140 + flowObjectiveService.forward(deviceId, objective.add());
141 + }
142 + } else {
143 + flowObjectiveService.forward(deviceId, objective.remove());
144 + }
145 + });
146 + }
147 +
148 + @Override
149 + public void programLocalOut(DeviceId deviceId,
150 + SegmentationId segmentationId,
151 + PortNumber outPort, MacAddress sourceMac,
152 + Objective.Operation type) {
153 + TrafficSelector selector = DefaultTrafficSelector.builder()
154 + .matchTunnelId(Long.parseLong(segmentationId.toString()))
155 + .matchEthDst(sourceMac).build();
156 + TrafficTreatment treatment = DefaultTrafficTreatment.builder()
157 + .setOutput(outPort).build();
158 + ForwardingObjective.Builder objective = DefaultForwardingObjective
159 + .builder().withTreatment(treatment).withSelector(selector)
160 + .fromApp(appId).withFlag(Flag.SPECIFIC)
161 + .withPriority(MAC_PRIORITY);
162 + if (type.equals(Objective.Operation.ADD)) {
163 + flowObjectiveService.forward(deviceId, objective.add());
164 + } else {
165 + flowObjectiveService.forward(deviceId, objective.remove());
166 + }
167 +
168 + }
169 +
170 + @Override
171 + public void programTunnelOut(DeviceId deviceId,
172 + SegmentationId segmentationId,
173 + PortNumber tunnelOutPort, MacAddress dstMac,
174 + Objective.Operation type) {
175 + TrafficSelector selector = DefaultTrafficSelector.builder()
176 + .matchEthDst(dstMac).add(Criteria.matchTunnelId(Long
177 + .parseLong(segmentationId.toString())))
178 + .build();
179 + TrafficTreatment treatment = DefaultTrafficTreatment.builder()
180 + .setOutput(tunnelOutPort).build();
181 + ForwardingObjective.Builder objective = DefaultForwardingObjective
182 + .builder().withTreatment(treatment).withSelector(selector)
183 + .fromApp(appId).withFlag(Flag.SPECIFIC)
184 + .withPriority(MAC_PRIORITY);
185 + if (type.equals(Objective.Operation.ADD)) {
186 + flowObjectiveService.forward(deviceId, objective.add());
187 + } else {
188 + flowObjectiveService.forward(deviceId, objective.remove());
189 + }
190 +
191 + }
192 +
193 +}
1 +/*
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 + */
16 +
17 +/**
18 + * VTN application that applies configuration and flows to the device.
19 + */
20 +package org.onosproject.vtn.table.impl;
1 +/*
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 + */
16 +
17 +/**
18 + * VTN application that applies configuration and flows to the device.
19 + */
20 +package org.onosproject.vtn.table;
1 +package org.onosproject.vtn.util;
2 +
3 +import static org.onlab.util.Tools.toHex;
4 +
5 +import java.net.URI;
6 +import java.net.URISyntaxException;
7 +import java.util.Calendar;
8 +
9 +import org.onosproject.core.IdGenerator;
10 +import org.onosproject.net.DeviceId;
11 +
12 +public final class DataPathIdGenerator implements IdGenerator {
13 + private static final String SCHEME = "of";
14 + private String ipAddress;
15 + private String timeStamp;
16 +
17 + private DataPathIdGenerator(Builder builder) {
18 + this.ipAddress = builder.ipAddress;
19 + Calendar cal = Calendar.getInstance();
20 + this.timeStamp = String.valueOf(cal.get(Calendar.SECOND))
21 + + String.valueOf(cal.get(Calendar.MILLISECOND));
22 + }
23 +
24 + @Override
25 + public long getNewId() {
26 + String dpid = ipAddress.replace(".", "") + timeStamp;
27 + return Long.parseLong(dpid);
28 + }
29 +
30 + public String getDpId() {
31 + return toHex(getNewId());
32 + }
33 +
34 + public DeviceId getDeviceId() {
35 + try {
36 + URI uri = new URI(SCHEME, toHex(getNewId()), null);
37 + return DeviceId.deviceId(uri);
38 + } catch (URISyntaxException e) {
39 + return null;
40 + }
41 + }
42 +
43 + /**
44 + * Returns a new builder.
45 + *
46 + * @return new builder
47 + */
48 + public static Builder builder() {
49 + return new Builder();
50 + }
51 +
52 + public static final class Builder {
53 + private String ipAddress;
54 +
55 + public Builder addIpAddress(String ipAddress) {
56 + this.ipAddress = ipAddress;
57 + return this;
58 + }
59 +
60 + public DataPathIdGenerator build() {
61 + return new DataPathIdGenerator(this);
62 + }
63 + }
64 +}
1 +/*
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 + */
16 +package org.onosproject.vtn.util;
17 +
18 +import java.util.Set;
19 +
20 +import org.onlab.packet.IpAddress;
21 +import org.onosproject.net.PortNumber;
22 +import org.onosproject.net.behaviour.BridgeConfig;
23 +import org.onosproject.net.behaviour.BridgeName;
24 +import org.onosproject.net.behaviour.DefaultTunnelDescription;
25 +import org.onosproject.net.behaviour.IpTunnelEndPoint;
26 +import org.onosproject.net.behaviour.TunnelConfig;
27 +import org.onosproject.net.behaviour.TunnelDescription;
28 +import org.onosproject.net.behaviour.TunnelEndPoint;
29 +import org.onosproject.net.driver.DriverHandler;
30 +
31 +/**
32 + * Applies configuration to the device.
33 + */
34 +public final class VtnConfig {
35 +
36 + private static final String DEFAULT_BRIDGE_NAME = "br-int";
37 +
38 + /**
39 + * Constructs a vtn config object. Utility classes should not have a
40 + * public or default constructor, otherwise IDE will compile unsuccessfully. This
41 + * class should not be instantiated.
42 + */
43 + private VtnConfig() {
44 + }
45 +
46 + /**
47 + * Creates or update bridge in the controller device.
48 + *
49 + * @param handler DriverHandler
50 + * @param dpid datapath id
51 + * @param exPortName external port name
52 + */
53 + public static void applyBridgeConfig(DriverHandler handler, String dpid, String exPortName) {
54 + BridgeConfig bridgeConfig = handler.behaviour(BridgeConfig.class);
55 + bridgeConfig.addBridge(BridgeName.bridgeName(DEFAULT_BRIDGE_NAME), dpid, exPortName);
56 + }
57 +
58 + /**
59 + * Creates or update tunnel in the controller device.
60 + *
61 + * @param handler DriverHandler
62 + * @param srcIp the ipAddress of the local controller device
63 + * @param dstIp the ipAddress of the remote controller device
64 + */
65 + public static void applyTunnelConfig(DriverHandler handler, IpAddress srcIp,
66 + IpAddress dstIp) {
67 + TunnelConfig tunnelConfig = handler.behaviour(TunnelConfig.class);
68 + TunnelEndPoint tunnelAsSrc = IpTunnelEndPoint.ipTunnelPoint(srcIp);
69 + TunnelEndPoint tunnelAsDst = IpTunnelEndPoint.ipTunnelPoint(dstIp);
70 + TunnelDescription tunnel = new DefaultTunnelDescription(
71 + tunnelAsSrc,
72 + tunnelAsDst,
73 + TunnelDescription.Type.VXLAN,
74 + null);
75 + tunnelConfig.createTunnel(tunnel);
76 + }
77 +
78 + /**
79 + * Creates or update tunnel in the controller device.
80 + *
81 + * @param handler DriverHandler
82 + * @param srcIp the ipAddress of the local controller device
83 + * @param dstIp the ipAddress of the remote controller device
84 + */
85 + public static void removeTunnelConfig(DriverHandler handler, IpAddress srcIp,
86 + IpAddress dstIp) {
87 + TunnelConfig tunnelConfig = handler.behaviour(TunnelConfig.class);
88 + TunnelEndPoint tunnelAsSrc = IpTunnelEndPoint.ipTunnelPoint(srcIp);
89 + TunnelEndPoint tunnelAsDst = IpTunnelEndPoint.ipTunnelPoint(dstIp);
90 + TunnelDescription tunnel = new DefaultTunnelDescription(
91 + tunnelAsSrc,
92 + tunnelAsDst,
93 + TunnelDescription.Type.VXLAN,
94 + null);
95 + tunnelConfig.removeTunnel(tunnel);
96 + }
97 +
98 + /**
99 + * Gets ports in the controller device.
100 + *
101 + * @param handler DriverHandler
102 + */
103 + public static Set<PortNumber> getPortNumbers(DriverHandler handler) {
104 + BridgeConfig bridgeConfig = handler.behaviour(BridgeConfig.class);
105 + return bridgeConfig.getPortNumbers();
106 + }
107 +
108 +}
1 +/*
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 + */
16 +package org.onosproject.vtn.util;
17 +
18 +import java.util.ArrayList;
19 +import java.util.Collection;
20 +
21 +import org.onosproject.net.AnnotationKeys;
22 +import org.onosproject.net.Device;
23 +import org.onosproject.net.DeviceId;
24 +import org.onosproject.net.Port;
25 +import org.onosproject.net.PortNumber;
26 +import org.slf4j.Logger;
27 +import org.slf4j.LoggerFactory;
28 +
29 +import com.google.common.collect.Sets;
30 +
31 +/**
32 + * VtnData utility class.
33 + */
34 +public final class VtnData {
35 +
36 + private static final Logger log = LoggerFactory.getLogger(VtnData.class);
37 + private static final String SWITCH_CHANNEL_ID = "channelId";
38 + private static final String PORT_HEAD = "vxlan";
39 +
40 + /**
41 + * Constructs a VtnData object. Utility classes should not have a public or
42 + * default constructor, otherwise IDE will compile unsuccessfully. This
43 + * class should not be instantiated.
44 + */
45 + private VtnData() {
46 + }
47 +
48 + /**
49 + * Get the ControllerIp from the device .
50 + *
51 + * @param device Device
52 + * @return Controller Ip
53 + */
54 + public static String getControllerIpOfSwitch(Device device) {
55 + String url = device.annotations().value(SWITCH_CHANNEL_ID);
56 + return url.substring(0, url.lastIndexOf(":"));
57 + }
58 +
59 + /**
60 + * Get the ControllerId from the device .
61 + *
62 + * @param device Device
63 + * @param devices Devices
64 + * @return Controller Id
65 + */
66 + public static DeviceId getControllerId(Device device,
67 + Iterable<Device> devices) {
68 + for (Device d : devices) {
69 + if (d.type() == Device.Type.CONTROLLER && d.id().toString()
70 + .contains(getControllerIpOfSwitch(device))) {
71 + return d.id();
72 + }
73 + }
74 + log.info("Can not find controller for device : {}", device.id());
75 + return null;
76 + }
77 +
78 + /**
79 + * Get local tunnel ports.
80 + *
81 + * @param ports Iterable of Port
82 + * @return Collection of PortNumber
83 + */
84 + public static Collection<PortNumber> getLocalTunnelPorts(Iterable<Port> ports) {
85 + Collection<PortNumber> localTunnelPorts = new ArrayList<>();
86 + Sets.newHashSet(ports).stream()
87 + .filter(p -> !p.number().equals(PortNumber.LOCAL))
88 + .forEach(p -> {
89 + if (p.annotations().value(AnnotationKeys.PORT_NAME)
90 + .startsWith(PORT_HEAD)) {
91 + localTunnelPorts.add(p.number());
92 + }
93 + });
94 + return localTunnelPorts;
95 + }
96 +
97 +}
1 +/*
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 + */
16 +
17 +/**
18 + * VTN application that applies configuration and flows to the device.
19 + */
20 +package org.onosproject.vtn.util;
...@@ -36,6 +36,15 @@ public interface BridgeConfig extends HandlerBehaviour { ...@@ -36,6 +36,15 @@ public interface BridgeConfig extends HandlerBehaviour {
36 void addBridge(BridgeName bridgeName); 36 void addBridge(BridgeName bridgeName);
37 37
38 /** 38 /**
39 + * Adds a bridge with given bridge name, dpid and exPortName.
40 + *
41 + * @param bridgeName bridge name
42 + * @param dpid dpid
43 + * @param exPortName external port name
44 + */
45 + void addBridge(BridgeName bridgeName, String dpid, String exPortName);
46 +
47 + /**
39 * Adds a bridge with given bridge name and dpid, and sets the controller 48 * Adds a bridge with given bridge name and dpid, and sets the controller
40 * of the bridge with given controllers. 49 * of the bridge with given controllers.
41 * 50 *
......
...@@ -54,6 +54,13 @@ public class OvsdbBridgeConfig extends AbstractHandlerBehaviour ...@@ -54,6 +54,13 @@ public class OvsdbBridgeConfig extends AbstractHandlerBehaviour
54 } 54 }
55 55
56 @Override 56 @Override
57 + public void addBridge(BridgeName bridgeName, String dpid, String exPortName) {
58 + DriverHandler handler = handler();
59 + OvsdbClientService clientService = getOvsdbClientService(handler);
60 + clientService.createBridge(bridgeName.name(), dpid, exPortName);
61 + }
62 +
63 + @Override
57 public boolean addBridge(BridgeName bridgeName, String dpid, List<ControllerInfo> controllers) { 64 public boolean addBridge(BridgeName bridgeName, String dpid, List<ControllerInfo> controllers) {
58 DriverHandler handler = handler(); 65 DriverHandler handler = handler();
59 OvsdbClientService clientService = getOvsdbClientService(handler); 66 OvsdbClientService clientService = getOvsdbClientService(handler);
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
16 package org.onosproject.ovsdb.controller; 16 package org.onosproject.ovsdb.controller;
17 17
18 import com.google.common.util.concurrent.ListenableFuture; 18 import com.google.common.util.concurrent.ListenableFuture;
19 +
19 import org.onlab.packet.IpAddress; 20 import org.onlab.packet.IpAddress;
20 import org.onosproject.net.DeviceId; 21 import org.onosproject.net.DeviceId;
21 import org.onosproject.net.behaviour.ControllerInfo; 22 import org.onosproject.net.behaviour.ControllerInfo;
...@@ -84,6 +85,15 @@ public interface OvsdbClientService extends OvsdbRPC { ...@@ -84,6 +85,15 @@ public interface OvsdbClientService extends OvsdbRPC {
84 void createBridge(String bridgeName); 85 void createBridge(String bridgeName);
85 86
86 /** 87 /**
88 + * Creates a bridge.
89 + *
90 + * @param bridgeName bridge name
91 + * @param dpid data path id
92 + * @param exPortName external port name
93 + */
94 + void createBridge(String bridgeName, String dpid, String exPortName);
95 +
96 + /**
87 * Creates a bridge with given name and dpid. 97 * Creates a bridge with given name and dpid.
88 * Sets the bridge's controller with given controllers. 98 * Sets the bridge's controller with given controllers.
89 * 99 *
......
...@@ -24,7 +24,9 @@ import com.google.common.collect.Sets; ...@@ -24,7 +24,9 @@ import com.google.common.collect.Sets;
24 import com.google.common.util.concurrent.Futures; 24 import com.google.common.util.concurrent.Futures;
25 import com.google.common.util.concurrent.ListenableFuture; 25 import com.google.common.util.concurrent.ListenableFuture;
26 import com.google.common.util.concurrent.SettableFuture; 26 import com.google.common.util.concurrent.SettableFuture;
27 +
27 import io.netty.channel.Channel; 28 import io.netty.channel.Channel;
29 +
28 import org.onlab.packet.IpAddress; 30 import org.onlab.packet.IpAddress;
29 import org.onosproject.net.DeviceId; 31 import org.onosproject.net.DeviceId;
30 import org.onosproject.net.behaviour.ControllerInfo; 32 import org.onosproject.net.behaviour.ControllerInfo;
...@@ -489,6 +491,76 @@ public class DefaultOvsdbClient ...@@ -489,6 +491,76 @@ public class DefaultOvsdbClient
489 } 491 }
490 492
491 @Override 493 @Override
494 + public void createBridge(String bridgeName, String dpid, String exPortName) {
495 + log.debug("create bridge {}", bridgeName);
496 +
497 + DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
498 + if (dbSchema == null) {
499 + log.warn("The schema is null");
500 + return;
501 + }
502 +
503 + Bridge bridge = (Bridge) TableGenerator.createTable(dbSchema,
504 + OvsdbTable.BRIDGE);
505 + if (bridge == null) {
506 + log.debug("Can not create bridge");
507 + return;
508 + }
509 +
510 + Set<String> failModes = new HashSet<>();
511 + failModes.add("secure");
512 + bridge.setFailMode(failModes);
513 +
514 + Set<String> protocols = new HashSet<>();
515 + protocols.add(OvsdbConstant.OPENFLOW13);
516 + bridge.setProtocols(protocols);
517 +
518 + String ovsUuid = getOvsUuid(OvsdbConstant.DATABASENAME);
519 + if (ovsUuid == null) {
520 + log.warn("The Open_vSwitch is null");
521 + return;
522 + }
523 +
524 + String bridgeUuid = getBridgeUuid(bridgeName);
525 + if (bridgeUuid == null) {
526 + log.debug("Create a new bridge");
527 +
528 + bridge.setName(bridgeName);
529 + if (dpid != null) {
530 + Map<String, String> options = new HashMap<>();
531 + options.put("datapath-id", dpid);
532 + bridge.setOtherConfig(options);
533 + }
534 + bridgeUuid = insertConfig(OvsdbConstant.BRIDGE, "_uuid",
535 + OvsdbConstant.DATABASENAME, "bridges",
536 + ovsUuid, bridge.getRow());
537 +
538 + if (bridgeUuid != null) {
539 + Port port = (Port) TableGenerator.createTable(dbSchema,
540 + OvsdbTable.PORT);
541 + if (port != null) {
542 + log.debug("the port is not null");
543 + port.setName(bridgeName);
544 +
545 + insertConfig(OvsdbConstant.PORT, "_uuid", "Bridge", "ports", bridgeUuid,
546 + port.getRow());
547 + }
548 + }
549 +
550 + } else {
551 + log.info("Update a bridge");
552 + updateConfig(OvsdbConstant.BRIDGE, "_uuid", bridgeUuid, bridge.getRow());
553 + }
554 + // Create external port
555 + if (exPortName != null) {
556 + createPort(bridgeName, exPortName);
557 + }
558 +
559 + setControllerAuto(bridgeUuid);
560 + log.info("Create bridge success");
561 + }
562 +
563 + @Override
492 public boolean createBridge(String bridgeName, String dpid, List<ControllerInfo> controllers) { 564 public boolean createBridge(String bridgeName, String dpid, List<ControllerInfo> controllers) {
493 565
494 DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME); 566 DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
......
...@@ -18,6 +18,7 @@ package org.onosproject.ovsdb.controller.driver; ...@@ -18,6 +18,7 @@ package org.onosproject.ovsdb.controller.driver;
18 18
19 import com.fasterxml.jackson.databind.JsonNode; 19 import com.fasterxml.jackson.databind.JsonNode;
20 import com.google.common.util.concurrent.ListenableFuture; 20 import com.google.common.util.concurrent.ListenableFuture;
21 +
21 import org.onlab.packet.IpAddress; 22 import org.onlab.packet.IpAddress;
22 import org.onosproject.net.DeviceId; 23 import org.onosproject.net.DeviceId;
23 import org.onosproject.net.behaviour.ControllerInfo; 24 import org.onosproject.net.behaviour.ControllerInfo;
...@@ -216,4 +217,9 @@ public class OvsdbClientServiceAdapter implements OvsdbClientService { ...@@ -216,4 +217,9 @@ public class OvsdbClientServiceAdapter implements OvsdbClientService {
216 public ListenableFuture<List<JsonNode>> transact(DatabaseSchema dbSchema, List<Operation> operations) { 217 public ListenableFuture<List<JsonNode>> transact(DatabaseSchema dbSchema, List<Operation> operations) {
217 return null; 218 return null;
218 } 219 }
220 +
221 + @Override
222 + public void createBridge(String bridgeName, String dpid, String exPortName) {
223 +
224 + }
219 } 225 }
......