Yuta HIGUCHI

Disconnect switch when Device was admin removed.

Change-Id: I8d55eda686d29b43540f5467739983564afde5af
...@@ -28,6 +28,10 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; ...@@ -28,6 +28,10 @@ import org.apache.felix.scr.annotations.ReferenceCardinality;
28 import org.apache.felix.scr.annotations.Service; 28 import org.apache.felix.scr.annotations.Service;
29 import org.onosproject.cfg.ComponentConfigService; 29 import org.onosproject.cfg.ComponentConfigService;
30 import org.onosproject.core.CoreService; 30 import org.onosproject.core.CoreService;
31 +import org.onosproject.net.device.DeviceEvent;
32 +import org.onosproject.net.device.DeviceEvent.Type;
33 +import org.onosproject.net.device.DeviceListener;
34 +import org.onosproject.net.device.DeviceService;
31 import org.onosproject.net.driver.DefaultDriverProviderService; 35 import org.onosproject.net.driver.DefaultDriverProviderService;
32 import org.onosproject.net.driver.DriverService; 36 import org.onosproject.net.driver.DriverService;
33 import org.onosproject.openflow.controller.DefaultOpenFlowPacketContext; 37 import org.onosproject.openflow.controller.DefaultOpenFlowPacketContext;
...@@ -72,6 +76,7 @@ import java.util.Collection; ...@@ -72,6 +76,7 @@ import java.util.Collection;
72 import java.util.Collections; 76 import java.util.Collections;
73 import java.util.LinkedList; 77 import java.util.LinkedList;
74 import java.util.List; 78 import java.util.List;
79 +import java.util.Optional;
75 import java.util.Set; 80 import java.util.Set;
76 import java.util.concurrent.ConcurrentHashMap; 81 import java.util.concurrent.ConcurrentHashMap;
77 import java.util.concurrent.ConcurrentMap; 82 import java.util.concurrent.ConcurrentMap;
...@@ -82,6 +87,7 @@ import java.util.concurrent.locks.Lock; ...@@ -82,6 +87,7 @@ import java.util.concurrent.locks.Lock;
82 import java.util.concurrent.locks.ReentrantLock; 87 import java.util.concurrent.locks.ReentrantLock;
83 88
84 import static org.onlab.util.Tools.groupedThreads; 89 import static org.onlab.util.Tools.groupedThreads;
90 +import static org.onosproject.openflow.controller.Dpid.dpid;
85 91
86 @Component(immediate = true) 92 @Component(immediate = true)
87 @Service 93 @Service
...@@ -106,6 +112,10 @@ public class OpenFlowControllerImpl implements OpenFlowController { ...@@ -106,6 +112,10 @@ public class OpenFlowControllerImpl implements OpenFlowController {
106 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 112 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
107 protected ComponentConfigService cfgService; 113 protected ComponentConfigService cfgService;
108 114
115 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
116 + protected DeviceService deviceService;
117 +
118 +
109 @Property(name = "openflowPorts", value = DEFAULT_OFPORT, 119 @Property(name = "openflowPorts", value = DEFAULT_OFPORT,
110 label = "Port numbers (comma separated) used by OpenFlow protocol; default is 6633,6653") 120 label = "Port numbers (comma separated) used by OpenFlow protocol; default is 6633,6653")
111 private String openflowPorts = DEFAULT_OFPORT; 121 private String openflowPorts = DEFAULT_OFPORT;
...@@ -161,11 +171,13 @@ public class OpenFlowControllerImpl implements OpenFlowController { ...@@ -161,11 +171,13 @@ public class OpenFlowControllerImpl implements OpenFlowController {
161 ArrayListMultimap.create(); 171 ArrayListMultimap.create();
162 172
163 private final Controller ctrl = new Controller(); 173 private final Controller ctrl = new Controller();
174 + private InternalDeviceListener listener = new InternalDeviceListener();
164 175
165 @Activate 176 @Activate
166 public void activate(ComponentContext context) { 177 public void activate(ComponentContext context) {
167 coreService.registerApplication(APP_ID, this::cleanup); 178 coreService.registerApplication(APP_ID, this::cleanup);
168 cfgService.registerProperties(getClass()); 179 cfgService.registerProperties(getClass());
180 + deviceService.addListener(listener);
169 ctrl.setConfigParams(context.getProperties()); 181 ctrl.setConfigParams(context.getProperties());
170 ctrl.start(agent, driverService); 182 ctrl.start(agent, driverService);
171 } 183 }
...@@ -182,6 +194,7 @@ public class OpenFlowControllerImpl implements OpenFlowController { ...@@ -182,6 +194,7 @@ public class OpenFlowControllerImpl implements OpenFlowController {
182 194
183 @Deactivate 195 @Deactivate
184 public void deactivate() { 196 public void deactivate() {
197 + deviceService.removeListener(listener);
185 cleanup(); 198 cleanup();
186 cfgService.unregisterProperties(getClass(), false); 199 cfgService.unregisterProperties(getClass(), false);
187 } 200 }
...@@ -521,6 +534,46 @@ public class OpenFlowControllerImpl implements OpenFlowController { ...@@ -521,6 +534,46 @@ public class OpenFlowControllerImpl implements OpenFlowController {
521 sw.setRole(role); 534 sw.setRole(role);
522 } 535 }
523 536
537 + class InternalDeviceListener implements DeviceListener {
538 +
539 + @Override
540 + public boolean isRelevant(DeviceEvent event) {
541 + return event.type() == Type.DEVICE_REMOVED;
542 + }
543 +
544 + @Override
545 + public void event(DeviceEvent event) {
546 + switch (event.type()) {
547 + case DEVICE_ADDED:
548 + break;
549 + case DEVICE_AVAILABILITY_CHANGED:
550 + break;
551 + case DEVICE_REMOVED:
552 + // Device administratively removed, disconnect
553 + Optional.ofNullable(getSwitch(dpid(event.subject().id().uri())))
554 + .ifPresent(OpenFlowSwitch::disconnectSwitch);
555 + break;
556 + case DEVICE_SUSPENDED:
557 + break;
558 + case DEVICE_UPDATED:
559 + break;
560 + case PORT_ADDED:
561 + break;
562 + case PORT_REMOVED:
563 + break;
564 + case PORT_STATS_UPDATED:
565 + break;
566 + case PORT_UPDATED:
567 + break;
568 + default:
569 + break;
570 +
571 + }
572 +
573 + }
574 +
575 + }
576 +
524 /** 577 /**
525 * Implementation of an OpenFlow Agent which is responsible for 578 * Implementation of an OpenFlow Agent which is responsible for
526 * keeping track of connected switches and the state in which 579 * keeping track of connected switches and the state in which
......
...@@ -33,6 +33,7 @@ import org.junit.Test; ...@@ -33,6 +33,7 @@ import org.junit.Test;
33 import org.onlab.junit.TestTools; 33 import org.onlab.junit.TestTools;
34 import org.onosproject.cfg.ComponentConfigService; 34 import org.onosproject.cfg.ComponentConfigService;
35 import org.onosproject.core.CoreService; 35 import org.onosproject.core.CoreService;
36 +import org.onosproject.net.device.DeviceServiceAdapter;
36 import org.onosproject.openflow.OpenflowSwitchDriverAdapter; 37 import org.onosproject.openflow.OpenflowSwitchDriverAdapter;
37 import org.onosproject.openflow.controller.Dpid; 38 import org.onosproject.openflow.controller.Dpid;
38 import org.onosproject.openflow.controller.OpenFlowSwitch; 39 import org.onosproject.openflow.controller.OpenFlowSwitch;
...@@ -143,6 +144,8 @@ public class OpenFlowControllerImplTest { ...@@ -143,6 +144,8 @@ public class OpenFlowControllerImplTest {
143 controller.cfgService = mockConfigService; 144 controller.cfgService = mockConfigService;
144 replay(mockConfigService); 145 replay(mockConfigService);
145 146
147 + controller.deviceService = new DeviceServiceAdapter();
148 +
146 ComponentContext mockContext = EasyMock.createMock(ComponentContext.class); 149 ComponentContext mockContext = EasyMock.createMock(ComponentContext.class);
147 Dictionary<String, Object> properties = new Hashtable<>(); 150 Dictionary<String, Object> properties = new Hashtable<>();
148 properties.put("openflowPorts", 151 properties.put("openflowPorts",
......