blob: 1f13346b540143f59136f8db8c5071d9b26cb652 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2014-present Open Networking Laboratory
Thomas Vachuska781d18b2014-10-27 10:31:25 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * 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
Thomas Vachuska781d18b2014-10-27 10:31:25 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * 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.
Thomas Vachuska781d18b2014-10-27 10:31:25 -070015 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.mobility;
Brian O'Connorca37aa22015-12-11 13:54:36 -080017import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
18import static org.onlab.util.Tools.groupedThreads;
alshabib4906fab2014-09-29 23:58:12 -070019import static org.slf4j.LoggerFactory.getLogger;
20
21import java.util.Collection;
22import java.util.List;
Brian O'Connorca37aa22015-12-11 13:54:36 -080023import java.util.concurrent.ExecutorService;
alshabib4906fab2014-09-29 23:58:12 -070024
25import org.apache.felix.scr.annotations.Activate;
26import org.apache.felix.scr.annotations.Component;
27import org.apache.felix.scr.annotations.Deactivate;
28import org.apache.felix.scr.annotations.Reference;
29import org.apache.felix.scr.annotations.ReferenceCardinality;
Brian O'Connorabafb502014-12-02 22:26:20 -080030import org.onosproject.core.ApplicationId;
31import org.onosproject.core.CoreService;
32import org.onosproject.net.Device;
33import org.onosproject.net.Host;
34import org.onosproject.net.device.DeviceService;
35import org.onosproject.net.flow.FlowRule;
36import org.onosproject.net.flow.FlowRuleService;
Sho SHIMIZUfbc80e52015-04-28 10:41:58 -070037import org.onosproject.net.flow.criteria.EthCriterion;
Brian O'Connorabafb502014-12-02 22:26:20 -080038import org.onosproject.net.flow.criteria.Criterion;
39import org.onosproject.net.flow.criteria.Criterion.Type;
40import org.onosproject.net.host.HostEvent;
41import org.onosproject.net.host.HostListener;
42import org.onosproject.net.host.HostService;
alshabib4906fab2014-09-29 23:58:12 -070043import org.onlab.packet.MacAddress;
44import org.slf4j.Logger;
45
46import com.google.common.collect.Lists;
47
48
49/**
alshabib0ff17ad2014-09-30 09:46:40 -070050 * Sample mobility application. Cleans up flowmods when a host moves.
alshabib4906fab2014-09-29 23:58:12 -070051 */
52@Component(immediate = true)
53public class HostMobility {
54
55 private final Logger log = getLogger(getClass());
56
57 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
58 protected HostService hostService;
59
60 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
61 protected FlowRuleService flowRuleService;
62
63 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
64 protected DeviceService deviceService;
65
alshabib92c65ad2014-10-08 21:56:05 -070066 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
67 protected CoreService coreService;
68
alshabib4906fab2014-09-29 23:58:12 -070069 private ApplicationId appId;
Brian O'Connorca37aa22015-12-11 13:54:36 -080070 private ExecutorService eventHandler;
alshabib4906fab2014-09-29 23:58:12 -070071
72 @Activate
73 public void activate() {
Brian O'Connorabafb502014-12-02 22:26:20 -080074 appId = coreService.registerApplication("org.onosproject.mobility");
Brian O'Connorca37aa22015-12-11 13:54:36 -080075 eventHandler = newSingleThreadScheduledExecutor(groupedThreads("onos/app-mobility", "event-handler"));
alshabib4906fab2014-09-29 23:58:12 -070076 hostService.addListener(new InternalHostListener());
77 log.info("Started with Application ID {}", appId.id());
78 }
79
80 @Deactivate
81 public void deactivate() {
Brian O'Connorca37aa22015-12-11 13:54:36 -080082 // TODO we never actually add any flow rules
alshabib4906fab2014-09-29 23:58:12 -070083 flowRuleService.removeFlowRulesById(appId);
Brian O'Connorca37aa22015-12-11 13:54:36 -080084 eventHandler.shutdown();
alshabib4906fab2014-09-29 23:58:12 -070085 log.info("Stopped");
86 }
87
88 public class InternalHostListener
Brian O'Connorca37aa22015-12-11 13:54:36 -080089 implements HostListener {
alshabib4906fab2014-09-29 23:58:12 -070090
91 @Override
92 public void event(HostEvent event) {
93 switch (event.type()) {
94 case HOST_ADDED:
95 case HOST_REMOVED:
96 case HOST_UPDATED:
97 // don't care if a host has been added, removed.
98 break;
99 case HOST_MOVED:
100 log.info("Host {} has moved; cleaning up.", event.subject());
Brian O'Connorca37aa22015-12-11 13:54:36 -0800101 eventHandler.execute(() -> cleanup(event.subject()));
alshabib4906fab2014-09-29 23:58:12 -0700102 break;
103
104 default:
105 break;
alshabib4906fab2014-09-29 23:58:12 -0700106 }
alshabib4906fab2014-09-29 23:58:12 -0700107 }
108
alshabib0ff17ad2014-09-30 09:46:40 -0700109 /**
110 * For a given host, remove any flow rule which references it's addresses.
111 * @param host the host to clean up for
112 */
alshabib4906fab2014-09-29 23:58:12 -0700113 private void cleanup(Host host) {
114 Iterable<Device> devices = deviceService.getDevices();
115 List<FlowRule> flowRules = Lists.newLinkedList();
116 for (Device device : devices) {
117 flowRules.addAll(cleanupDevice(device, host));
118 }
119 FlowRule[] flows = new FlowRule[flowRules.size()];
120 flows = flowRules.toArray(flows);
121 flowRuleService.removeFlowRules(flows);
122 }
123
124 private Collection<? extends FlowRule> cleanupDevice(Device device, Host host) {
125 List<FlowRule> flowRules = Lists.newLinkedList();
126 MacAddress mac = host.mac();
127 for (FlowRule rule : flowRuleService.getFlowEntries(device.id())) {
128 for (Criterion c : rule.selector().criteria()) {
129 if (c.type() == Type.ETH_DST || c.type() == Type.ETH_SRC) {
130 EthCriterion eth = (EthCriterion) c;
131 if (eth.mac().equals(mac)) {
132 flowRules.add(rule);
alshabib4906fab2014-09-29 23:58:12 -0700133 }
134 }
135 }
136 }
alshabib4906fab2014-09-29 23:58:12 -0700137 return flowRules;
138 }
alshabib4906fab2014-09-29 23:58:12 -0700139 }
alshabib4906fab2014-09-29 23:58:12 -0700140}
141
142