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; | ... | ... |
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 | } | ... | ... |
-
Please register or login to post a comment