blob: 495fa0093fe1b5182aa9c6120856d3a2045db068 [file] [log] [blame]
samuela5e17fc2015-07-29 15:46:40 +08001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.vtn.impl;
17
18import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
19import static org.onlab.util.Tools.groupedThreads;
20import static org.slf4j.LoggerFactory.getLogger;
21
22import java.util.HashSet;
23import java.util.List;
24import java.util.Set;
25import java.util.concurrent.ScheduledExecutorService;
26
27import org.apache.felix.scr.annotations.Activate;
28import org.apache.felix.scr.annotations.Component;
29import org.apache.felix.scr.annotations.Deactivate;
30import org.apache.felix.scr.annotations.Reference;
31import org.apache.felix.scr.annotations.ReferenceCardinality;
32import org.apache.felix.scr.annotations.Service;
33import org.onlab.packet.IpAddress;
34import org.onlab.packet.MacAddress;
35import org.onlab.util.KryoNamespace;
36import org.onosproject.app.vtnrsc.SegmentationId;
37import org.onosproject.app.vtnrsc.TenantNetwork;
38import org.onosproject.app.vtnrsc.VirtualPort;
39import org.onosproject.app.vtnrsc.VirtualPortId;
40import org.onosproject.app.vtnrsc.tenantnetwork.TenantNetworkService;
41import org.onosproject.app.vtnrsc.virtualport.VirtualPortService;
42import org.onosproject.core.ApplicationId;
43import org.onosproject.core.CoreService;
44import org.onosproject.net.Device;
45import org.onosproject.net.DeviceId;
46import org.onosproject.net.Host;
47import org.onosproject.net.HostId;
48import org.onosproject.net.Port;
49import org.onosproject.net.PortNumber;
50import org.onosproject.net.behaviour.BridgeConfig;
51import org.onosproject.net.behaviour.BridgeName;
52import org.onosproject.net.behaviour.DefaultTunnelDescription;
53import org.onosproject.net.behaviour.IpTunnelEndPoint;
54import org.onosproject.net.behaviour.TunnelConfig;
55import org.onosproject.net.behaviour.TunnelDescription;
56import org.onosproject.net.behaviour.TunnelEndPoint;
57import org.onosproject.net.device.DeviceEvent;
58import org.onosproject.net.device.DeviceListener;
59import org.onosproject.net.device.DeviceService;
60import org.onosproject.net.driver.DriverHandler;
61import org.onosproject.net.driver.DriverService;
62import org.onosproject.net.flow.DefaultTrafficSelector;
63import org.onosproject.net.flow.DefaultTrafficTreatment;
64import org.onosproject.net.flow.FlowRuleService;
65import org.onosproject.net.flow.TrafficSelector;
66import org.onosproject.net.flow.TrafficTreatment;
67import org.onosproject.net.flow.criteria.Criteria;
68import org.onosproject.net.flow.instructions.Instructions;
69import org.onosproject.net.flowobjective.DefaultForwardingObjective;
70import org.onosproject.net.flowobjective.FlowObjectiveService;
71import org.onosproject.net.flowobjective.ForwardingObjective;
72import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
73import org.onosproject.net.flowobjective.Objective;
74import org.onosproject.net.host.HostEvent;
75import org.onosproject.net.host.HostListener;
76import org.onosproject.net.host.HostService;
77import org.onosproject.store.serializers.KryoNamespaces;
78import org.onosproject.store.service.EventuallyConsistentMap;
79import org.onosproject.store.service.StorageService;
80import org.onosproject.store.service.WallClockTimestamp;
81import org.onosproject.vtn.VTNService;
82import org.slf4j.Logger;
83
samuel1e9044c2015-08-05 18:44:18 +080084import com.google.common.collect.Sets;
85
samuela5e17fc2015-07-29 15:46:40 +080086/**
87 * Provides implementation of VTNService.
88 */
89@Component(immediate = true)
90@Service
91public class VTNManager implements VTNService {
92 private final Logger log = getLogger(getClass());
93
94 private static final String APP_ID = "org.onosproject.app.vtn";
95 private ScheduledExecutorService backgroundService;
96 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
97 protected DeviceService deviceService;
98 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
99 protected HostService hostService;
100 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
101 protected FlowRuleService flowRuleService;
102 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
103 protected CoreService coreService;
104 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
105 protected StorageService storageService;
106 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
107 protected TenantNetworkService tenantNetworkService;
108 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
109 protected VirtualPortService virtualPortService;
110 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
111 protected DriverService driverService;
112 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
113 protected FlowObjectiveService flowObjectiveService;
114 private EventuallyConsistentMap<HostId, SegmentationId> binding;
115 private ApplicationId appId;
116 private HostListener hostListener = new InnerHostListener();
117 private DeviceListener deviceListener = new InnerDeviceListener();
118 private static final String IFACEID = "ifaceid";
119 private static final String PORT_HEAD = "vxlan";
120 private static final int MAC_TABLE = 40;
samuela5e17fc2015-07-29 15:46:40 +0800121 private static final String DEFAULT_BRIDGE_NAME = "br-int";
122 private static final String CONTROLLER_IP_KEY = "ipaddress";
123
124 @Activate
125 public void activate() {
126 KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
127 .register(KryoNamespaces.API);
128 appId = coreService.registerApplication(APP_ID);
129 deviceService.addListener(deviceListener);
130 hostService.addListener(hostListener);
131 backgroundService = newSingleThreadScheduledExecutor(groupedThreads("onos-apps/vtn",
132 "manager-background"));
133 binding = storageService
134 .<HostId, SegmentationId>eventuallyConsistentMapBuilder()
135 .withName("all_tunnel").withSerializer(serializer)
136 .withTimestampProvider((k, v) -> new WallClockTimestamp())
137 .build();
138 log.info("Started");
139 }
140
141 @Deactivate
142 public void deactivate() {
143 backgroundService.shutdown();
144 binding.destroy();
145 log.info("Stopped");
146 }
147
148 @Override
149 public void onServerDetected(Device device) {
150 Iterable<Device> devices = deviceService.getAvailableDevices();
151 DriverHandler handler = driverService.createHandler(device.id());
samuela5e17fc2015-07-29 15:46:40 +0800152 BridgeConfig bridgeConfig = handler.behaviour(BridgeConfig.class);
153 bridgeConfig.addBridge(BridgeName.bridgeName(DEFAULT_BRIDGE_NAME));
154 String ipAddress = device.annotations().value(CONTROLLER_IP_KEY);
155 IpAddress ip = IpAddress.valueOf(ipAddress);
samuel1e9044c2015-08-05 18:44:18 +0800156 Sets.newHashSet(devices)
157 .stream()
158 .filter(d -> d.type() == Device.Type.CONTROLLER)
159 .filter(d -> !device.id().equals(d.id()))
160 .forEach(d -> {
161 String ipAddress1 = d.annotations()
162 .value(CONTROLLER_IP_KEY);
163 IpAddress ip1 = IpAddress.valueOf(ipAddress1);
164 applyTunnelConfig(ip, ip1, handler);
165 DriverHandler handler1 = driverService
166 .createHandler(d.id());
167 applyTunnelConfig(ip1, ip, handler1);
168 });
samuela5e17fc2015-07-29 15:46:40 +0800169 }
170
171 @Override
172 public void onServerVanished(Device device) {
173 Iterable<Device> devices = deviceService.getAvailableDevices();
samuela5e17fc2015-07-29 15:46:40 +0800174 String ipAddress = device.annotations().value(CONTROLLER_IP_KEY);
samuel1e9044c2015-08-05 18:44:18 +0800175 IpAddress dst = IpAddress.valueOf(ipAddress);
176 Sets.newHashSet(devices)
177 .stream()
178 .filter(d -> d.type() == Device.Type.CONTROLLER)
179 .filter(d -> !device.id().equals(d.id()))
180 .forEach(d -> {
181 String ipAddress1 = d.annotations()
182 .value(CONTROLLER_IP_KEY);
183 DriverHandler handler = driverService
184 .createHandler(d.id());
185 IpAddress src = IpAddress.valueOf(ipAddress1);
186 removeTunnelConfig(src, dst, handler);
187 });
188 }
189
190 private void applyTunnelConfig(IpAddress src, IpAddress dst,
191 DriverHandler handler) {
192 TunnelEndPoint tunnelAsSrc = IpTunnelEndPoint.ipTunnelPoint(src);
193 TunnelEndPoint tunnelAsDst = IpTunnelEndPoint.ipTunnelPoint(dst);
194 TunnelDescription tunnel = new DefaultTunnelDescription(
195 tunnelAsSrc,
196 tunnelAsDst,
197 TunnelDescription.Type.VXLAN,
198 null);
199 TunnelConfig config = handler.behaviour(TunnelConfig.class);
200 config.createTunnel(tunnel);
201 }
202
203 private void removeTunnelConfig(IpAddress src, IpAddress dst,
204 DriverHandler handler) {
205 TunnelEndPoint tunnelAsSrc = IpTunnelEndPoint.ipTunnelPoint(src);
206 TunnelEndPoint tunnelAsDst = IpTunnelEndPoint.ipTunnelPoint(dst);
207 TunnelDescription tunnel = new DefaultTunnelDescription(
208 tunnelAsSrc,
209 tunnelAsDst,
210 TunnelDescription.Type.VXLAN,
211 null);
212 TunnelConfig config = handler.behaviour(TunnelConfig.class);
213 config.removeTunnel(tunnel);
samuela5e17fc2015-07-29 15:46:40 +0800214 }
215
216 @Override
217 public void onOvsDetected(Device device) {
218 programMacDefaultRules(device.id(), appId, Objective.Operation.ADD);
219 programPortDefaultRules(device.id(), appId, Objective.Operation.ADD);
220 }
221
222 @Override
223 public void onOvsVanished(Device device) {
224 programMacDefaultRules(device.id(), appId, Objective.Operation.REMOVE);
225 programPortDefaultRules(device.id(), appId, Objective.Operation.REMOVE);
226 }
227
228 @Override
229 public void onHostDetected(Host host) {
230 String ifaceId = host.annotations().value(IFACEID);
231 VirtualPortId portId = VirtualPortId.portId(ifaceId);
232 VirtualPort port = virtualPortService.getPort(portId);
233 TenantNetwork network = tenantNetworkService.getNetwork(port
234 .networkId());
235 binding.put(host.id(), network.segmentationId());
236 DeviceId deviceId = host.location().deviceId();
237 List<Port> allPorts = deviceService.getPorts(deviceId);
238 PortNumber inPort = host.location().port();
239 Set<Port> localPorts = new HashSet<>();
240 allPorts.forEach(p -> {
241 if (!p.number().name().startsWith(PORT_HEAD)) {
242 localPorts.add(p);
243 }
244 });
245 programLocalBcastRules(deviceId, network.segmentationId(), inPort,
246 allPorts, appId, Objective.Operation.ADD);
247 programLocalOut(deviceId, network.segmentationId(), inPort, host.mac(),
248 appId, Objective.Operation.ADD);
249 programTunnelFloodOut(deviceId, network.segmentationId(), inPort,
250 localPorts, appId, Objective.Operation.ADD);
251 programTunnelOut(deviceId, network.segmentationId(), inPort,
252 host.mac(), appId, Objective.Operation.ADD);
253 programLocalIn(deviceId, network.segmentationId(), inPort, host.mac(),
254 appId, Objective.Operation.ADD);
255 programTunnelIn(deviceId, network.segmentationId(), inPort, host.mac(),
256 appId, Objective.Operation.ADD);
257 }
258
259 @Override
260 public void onHostVanished(Host host) {
261 SegmentationId segId = binding.remove(host.id());
262 DeviceId deviceId = host.location().deviceId();
263 List<Port> allPorts = deviceService.getPorts(deviceId);
264 PortNumber inPort = host.location().port();
265 Set<Port> localPorts = new HashSet<>();
266 allPorts.forEach(p -> {
267 if (!p.number().name().startsWith(PORT_HEAD)) {
268 localPorts.add(p);
269 }
270 });
271 programLocalBcastRules(deviceId, segId, inPort, allPorts, appId,
272 Objective.Operation.REMOVE);
273 programLocalOut(deviceId, segId, inPort, host.mac(), appId,
274 Objective.Operation.REMOVE);
275 programTunnelFloodOut(deviceId, segId, inPort, localPorts, appId,
276 Objective.Operation.REMOVE);
277 programTunnelOut(deviceId, segId, inPort, host.mac(), appId,
278 Objective.Operation.REMOVE);
279 programLocalIn(deviceId, segId, inPort, host.mac(), appId,
280 Objective.Operation.REMOVE);
281 programTunnelIn(deviceId, segId, inPort, host.mac(), appId,
282 Objective.Operation.REMOVE);
283 }
284
285 private class InnerDeviceListener implements DeviceListener {
286
287 @Override
288 public void event(DeviceEvent event) {
289 Device device = event.subject();
290 if (Device.Type.CONTROLLER == device.type()
291 && DeviceEvent.Type.DEVICE_ADDED == event.type()) {
292 backgroundService.execute(() -> {
293 onServerDetected(device);
294 });
295 } else if (Device.Type.CONTROLLER == device.type()
samuel1e9044c2015-08-05 18:44:18 +0800296 && DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED == event
297 .type()) {
samuela5e17fc2015-07-29 15:46:40 +0800298 backgroundService.execute(() -> {
299 onServerVanished(device);
300 });
301 } else if (Device.Type.SWITCH == device.type()
302 && DeviceEvent.Type.DEVICE_ADDED == event.type()) {
303 backgroundService.execute(() -> {
304 onOvsDetected(device);
305 });
306 } else if (Device.Type.SWITCH == device.type()
samuel1e9044c2015-08-05 18:44:18 +0800307 && DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED == event
308 .type()) {
samuela5e17fc2015-07-29 15:46:40 +0800309 backgroundService.execute(() -> {
310 onOvsVanished(device);
311 });
312 } else {
313 log.info("do nothing for this device type");
314 }
315 }
316
317 }
318
319 private class InnerHostListener implements HostListener {
320
321 @Override
322 public void event(HostEvent event) {
323 Host host = event.subject();
324 if (HostEvent.Type.HOST_ADDED == event.type()) {
325 backgroundService.execute(() -> {
326 onHostDetected(host);
327 });
328 } else if (HostEvent.Type.HOST_REMOVED == event.type()) {
329 backgroundService.execute(() -> {
330 onHostVanished(host);
331 });
332 } else {
333 log.info("unknow host");
334 }
335 }
336
337 }
338
samuel1e9044c2015-08-05 18:44:18 +0800339 // Used to forward the flows to the local VM.
samuela5e17fc2015-07-29 15:46:40 +0800340 private void programLocalOut(DeviceId dpid, SegmentationId segmentationId,
341 PortNumber outPort, MacAddress sourceMac,
342 ApplicationId appid, Objective.Operation type) {
343 TrafficSelector selector = DefaultTrafficSelector.builder()
samuel1e9044c2015-08-05 18:44:18 +0800344 .matchEthDst(sourceMac).build();
samuela5e17fc2015-07-29 15:46:40 +0800345 TrafficTreatment treatment = DefaultTrafficTreatment
346 .builder()
347 .add(Instructions.modTunnelId(Long.parseLong(segmentationId
348 .toString()))).setOutput(outPort).build();
349 ForwardingObjective.Builder objective = DefaultForwardingObjective
350 .builder().withTreatment(treatment).withSelector(selector)
351 .fromApp(appId).withFlag(Flag.SPECIFIC);
352 if (type.equals(Objective.Operation.ADD)) {
353 flowObjectiveService.forward(dpid, objective.add());
354 } else {
355 flowObjectiveService.forward(dpid, objective.remove());
356 }
357
358 }
359
samuel1e9044c2015-08-05 18:44:18 +0800360 // Used to forward the flows to the remote VM via VXLAN tunnel.
samuela5e17fc2015-07-29 15:46:40 +0800361 private void programTunnelOut(DeviceId dpid, SegmentationId segmentationId,
362 PortNumber outPort, MacAddress sourceMac,
363 ApplicationId appid, Objective.Operation type) {
364 TrafficSelector selector = DefaultTrafficSelector.builder()
samuel1e9044c2015-08-05 18:44:18 +0800365 .matchEthDst(sourceMac).build();
samuela5e17fc2015-07-29 15:46:40 +0800366 TrafficTreatment treatment = DefaultTrafficTreatment
367 .builder()
368 .add(Instructions.modTunnelId(Long.parseLong(segmentationId
369 .toString()))).setOutput(outPort).build();
370 ForwardingObjective.Builder objective = DefaultForwardingObjective
371 .builder().withTreatment(treatment).withSelector(selector)
372 .fromApp(appId).makePermanent().withFlag(Flag.SPECIFIC);
373 if (type.equals(Objective.Operation.ADD)) {
374 flowObjectiveService.forward(dpid, objective.add());
375 } else {
376 flowObjectiveService.forward(dpid, objective.remove());
377 }
378 }
379
samuel1e9044c2015-08-05 18:44:18 +0800380 // Used to forward multicast flows to remote VMs of the same tenant via
381 // VXLAN tunnel.
samuela5e17fc2015-07-29 15:46:40 +0800382 private void programTunnelFloodOut(DeviceId dpid,
383 SegmentationId segmentationId,
384 PortNumber ofPortOut,
385 Iterable<Port> localports,
386 ApplicationId appid,
387 Objective.Operation type) {
388 TrafficSelector selector = DefaultTrafficSelector
389 .builder()
390 .matchInPort(ofPortOut)
samuel1e9044c2015-08-05 18:44:18 +0800391
samuela5e17fc2015-07-29 15:46:40 +0800392 .add(Criteria.matchTunnelId(Long.parseLong(segmentationId
393 .toString()))).matchEthDst(MacAddress.BROADCAST)
394 .build();
395 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
samuela5e17fc2015-07-29 15:46:40 +0800396 for (Port outport : localports) {
397 treatment.setOutput(outport.number());
398 }
399
400 ForwardingObjective.Builder objective = DefaultForwardingObjective
401 .builder().withTreatment(treatment.build())
samuel1e9044c2015-08-05 18:44:18 +0800402 .withSelector(selector).fromApp(appId).makePermanent()
403 .withFlag(Flag.SPECIFIC);
samuela5e17fc2015-07-29 15:46:40 +0800404 if (type.equals(Objective.Operation.ADD)) {
405 flowObjectiveService.forward(dpid, objective.add());
406 } else {
407 flowObjectiveService.forward(dpid, objective.remove());
408 }
409 }
410
samuel1e9044c2015-08-05 18:44:18 +0800411 // Applies default flows to mac table.
samuela5e17fc2015-07-29 15:46:40 +0800412 private void programMacDefaultRules(DeviceId dpid, ApplicationId appid,
413 Objective.Operation type) {
samuel1e9044c2015-08-05 18:44:18 +0800414 TrafficSelector selector = DefaultTrafficSelector.builder().build();
samuela5e17fc2015-07-29 15:46:40 +0800415 TrafficTreatment treatment = DefaultTrafficTreatment.builder().drop()
416 .build();
samuela5e17fc2015-07-29 15:46:40 +0800417 ForwardingObjective.Builder objective = DefaultForwardingObjective
418 .builder().withTreatment(treatment).withSelector(selector)
419 .fromApp(appId).makePermanent().withFlag(Flag.SPECIFIC);
420 if (type.equals(Objective.Operation.ADD)) {
421 flowObjectiveService.forward(dpid, objective.add());
422 } else {
423 flowObjectiveService.forward(dpid, objective.remove());
424 }
425 }
426
samuel1e9044c2015-08-05 18:44:18 +0800427 // Used to forward the flows to the local VMs with the same tenant.
samuela5e17fc2015-07-29 15:46:40 +0800428 private void programLocalBcastRules(DeviceId dpid,
429 SegmentationId segmentationId,
430 PortNumber inPort, List<Port> allports,
431 ApplicationId appid,
432 Objective.Operation type) {
433 TrafficSelector selector = DefaultTrafficSelector
434 .builder()
435 .matchInPort(inPort)
samuela5e17fc2015-07-29 15:46:40 +0800436 .matchEthDst(MacAddress.BROADCAST)
437 .add(Criteria.matchTunnelId(Long.parseLong(segmentationId
438 .toString()))).build();
439 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
440
441 for (Port outport : allports) {
442 if (inPort != outport.number()) {
443 treatment.setOutput(outport.number());
444 }
445 }
446 ForwardingObjective.Builder objective = DefaultForwardingObjective
447 .builder().withTreatment(treatment.build())
448 .withSelector(selector).fromApp(appId).makePermanent()
449 .withFlag(Flag.SPECIFIC);
450 if (type.equals(Objective.Operation.ADD)) {
451 flowObjectiveService.forward(dpid, objective.add());
452 } else {
453 flowObjectiveService.forward(dpid, objective.remove());
454 }
455 }
456
samuel1e9044c2015-08-05 18:44:18 +0800457 // Used to apply local entry flow.
samuela5e17fc2015-07-29 15:46:40 +0800458 private void programLocalIn(DeviceId dpid, SegmentationId segmentationId,
459 PortNumber inPort, MacAddress srcMac,
460 ApplicationId appid, Objective.Operation type) {
461 TrafficSelector selector = DefaultTrafficSelector.builder()
samuel1e9044c2015-08-05 18:44:18 +0800462 .matchInPort(inPort).matchEthSrc(srcMac).build();
samuela5e17fc2015-07-29 15:46:40 +0800463 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
samuela5e17fc2015-07-29 15:46:40 +0800464 treatment.add(Instructions.modTunnelId(Long.parseLong(segmentationId
465 .toString())));
466 treatment.transition(MAC_TABLE);
467 ForwardingObjective.Builder objective = DefaultForwardingObjective
468 .builder().withTreatment(treatment.build())
469 .withSelector(selector).fromApp(appId).makePermanent()
470 .withFlag(Flag.SPECIFIC);
471 if (type.equals(Objective.Operation.ADD)) {
472 flowObjectiveService.forward(dpid, objective.add());
473 } else {
474 flowObjectiveService.forward(dpid, objective.remove());
475 }
476 }
477
samuel1e9044c2015-08-05 18:44:18 +0800478 // Used to forward the flows from the egress tunnel to the VM.
samuela5e17fc2015-07-29 15:46:40 +0800479 private void programTunnelIn(DeviceId dpid, SegmentationId segmentationId,
480 PortNumber inPort, MacAddress sourceMac,
481 ApplicationId appid, Objective.Operation type) {
482 TrafficSelector selector = DefaultTrafficSelector
483 .builder()
484 .matchInPort(inPort)
samuela5e17fc2015-07-29 15:46:40 +0800485 .add(Criteria.matchTunnelId(Long.parseLong(segmentationId
486 .toString()))).build();
487 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
488 .transition(MAC_TABLE).build();
489
490 ForwardingObjective.Builder objective = DefaultForwardingObjective
491 .builder().withTreatment(treatment).withSelector(selector)
492 .fromApp(appId).makePermanent().withFlag(Flag.SPECIFIC);
493 if (type.equals(Objective.Operation.ADD)) {
494 flowObjectiveService.forward(dpid, objective.add());
495 } else {
496 flowObjectiveService.forward(dpid, objective.remove());
497 }
498 }
499
samuel1e9044c2015-08-05 18:44:18 +0800500 // Applies the default flows to port table.
samuela5e17fc2015-07-29 15:46:40 +0800501 private void programPortDefaultRules(DeviceId dpid, ApplicationId appid,
502 Objective.Operation type) {
samuel1e9044c2015-08-05 18:44:18 +0800503 TrafficSelector selector = DefaultTrafficSelector.builder().build();
samuela5e17fc2015-07-29 15:46:40 +0800504 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
505 .transition(MAC_TABLE).build();
506 ForwardingObjective.Builder objective = DefaultForwardingObjective
507 .builder().withTreatment(treatment).withSelector(selector)
508 .fromApp(appId).makePermanent().withFlag(Flag.SPECIFIC);
509 if (type.equals(Objective.Operation.ADD)) {
510 flowObjectiveService.forward(dpid, objective.add());
511 } else {
512 flowObjectiveService.forward(dpid, objective.remove());
513 }
514 }
515}