Support Neutron network/port admin state up/down configuration
Change-Id: I075c0abda0ea9216ac79c2eb65eb31294e952bf5
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java
index 6c9e3ea..332ed7f 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java
@@ -23,8 +23,10 @@
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.Ethernet;
-import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
+import org.onosproject.cluster.ClusterService;
+import org.onosproject.cluster.LeadershipService;
+import org.onosproject.cluster.NodeId;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.mastership.MastershipService;
@@ -41,6 +43,8 @@
import org.onosproject.openstacknetworking.api.InstancePortListener;
import org.onosproject.openstacknetworking.api.InstancePortService;
import org.onosproject.openstacknetworking.api.OpenstackFlowRuleService;
+import org.onosproject.openstacknetworking.api.OpenstackNetworkEvent;
+import org.onosproject.openstacknetworking.api.OpenstackNetworkListener;
import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
import org.onosproject.openstacknetworking.api.OpenstackSecurityGroupService;
import org.onosproject.openstacknetworking.util.RulePopulatorUtil;
@@ -51,6 +55,7 @@
import org.openstack4j.model.network.Port;
import org.slf4j.Logger;
+import java.util.Objects;
import java.util.concurrent.ExecutorService;
import static java.util.concurrent.Executors.newSingleThreadExecutor;
@@ -96,6 +101,15 @@
protected DeviceService deviceService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DriverService driverService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected ClusterService clusterService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected LeadershipService leadershipService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected OpenstackFlowRuleService osFlowRuleService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -108,26 +122,29 @@
protected OpenstackNodeService osNodeService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected DriverService driverService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected OpenstackSecurityGroupService securityGroupService;
private final ExecutorService eventExecutor = newSingleThreadExecutor(
groupedThreads(this.getClass().getSimpleName(), "event-handler"));
private final InstancePortListener instancePortListener = new InternalInstancePortListener();
+ private final InternalOpenstackNetworkListener osNetworkListener =
+ new InternalOpenstackNetworkListener();
private ApplicationId appId;
+ private NodeId localNodeId;
@Activate
void activate() {
appId = coreService.registerApplication(OPENSTACK_NETWORKING_APP_ID);
+ localNodeId = clusterService.getLocalNode().id();
instancePortService.addListener(instancePortListener);
+ osNetworkService.addListener(osNetworkListener);
log.info("Started");
}
@Deactivate
void deactivate() {
+ osNetworkService.removeListener(osNetworkListener);
instancePortService.removeListener(instancePortListener);
eventExecutor.shutdown();
@@ -499,43 +516,75 @@
install);
}
- private void setNetworkAdminRules(Network network, boolean install) {
- TrafficSelector selector;
- if (network.getNetworkType() == NetworkType.VXLAN) {
+ private void setNetworkBlockRules(Network network, boolean install) {
- selector = DefaultTrafficSelector.builder()
- .matchTunnelId(Long.valueOf(network.getProviderSegID()))
- .build();
- } else {
- selector = DefaultTrafficSelector.builder()
- .matchVlanId(VlanId.vlanId(network.getProviderSegID()))
- .build();
+ NetworkType type = network.getNetworkType();
+
+ // TODO: we block a network traffic by referring to segment ID for now
+ // we might need to find a better way to block the traffic of a network
+ // in case the segment ID is overlapped in different types network (VXLAN, VLAN)
+ switch (type) {
+ case VXLAN:
+ setNetworkBlockRulesForVxlan(network.getProviderSegID(), install);
+ break;
+ case VLAN:
+ setNetworkBlockRulesForVlan(network.getProviderSegID(), install);
+ break;
+ case FLAT:
+ // TODO: need to find a way to block flat typed network
+ break;
+ default:
+ break;
}
+ }
+
+ private void setNetworkBlockRulesForVxlan(String segmentId, boolean install) {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchTunnelId(Long.valueOf(segmentId))
+ .build();
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
.drop()
.build();
- osNodeService.completeNodes().stream()
- .filter(osNode -> osNode.type() == COMPUTE)
+ osNodeService.completeNodes(COMPUTE)
.forEach(osNode ->
osFlowRuleService.setRule(
- appId,
- osNode.intgBridge(),
- selector,
- treatment,
- PRIORITY_ADMIN_RULE,
- ACL_TABLE,
- install)
+ appId,
+ osNode.intgBridge(),
+ selector,
+ treatment,
+ PRIORITY_ADMIN_RULE,
+ ACL_TABLE,
+ install)
);
}
- // TODO: need to be purged sooner or later
- private void setPortAdminRules(Port port, boolean install) {
- InstancePort instancePort =
- instancePortService.instancePort(MacAddress.valueOf(port.getMacAddress()));
+ private void setNetworkBlockRulesForVlan(String segmentId, boolean install) {
TrafficSelector selector = DefaultTrafficSelector.builder()
- .matchInPort(instancePort.portNumber())
+ .matchTunnelId(Long.valueOf(segmentId))
+ .build();
+
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .drop()
+ .build();
+
+ osNodeService.completeNodes(COMPUTE)
+ .forEach(osNode ->
+ osFlowRuleService.setRule(
+ appId,
+ osNode.intgBridge(),
+ selector,
+ treatment,
+ PRIORITY_ADMIN_RULE,
+ ACL_TABLE,
+ install)
+ );
+ }
+
+ private void setPortBlockRules(InstancePort instPort, boolean install) {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchInPort(instPort.portNumber())
.build();
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
@@ -544,7 +593,7 @@
osFlowRuleService.setRule(
appId,
- instancePort.deviceId(),
+ instPort.deviceId(),
selector,
treatment,
PRIORITY_ADMIN_RULE,
@@ -606,6 +655,7 @@
@Override
public void event(InstancePortEvent event) {
InstancePort instPort = event.subject();
+ Port osPort = osNetworkService.port(instPort.portId());
switch (event.type()) {
case OPENSTACK_INSTANCE_PORT_DETECTED:
@@ -617,6 +667,11 @@
eventExecutor.execute(() -> instPortDetected(instPort));
+ if (osPort != null) {
+ eventExecutor.execute(() ->
+ setPortBlockRules(instPort, !osPort.isAdminStateUp()));
+ }
+
break;
case OPENSTACK_INSTANCE_TERMINATED:
log.info("SwitchingHandler: Instance port terminated MAC:{} IP:{}",
@@ -632,6 +687,10 @@
eventExecutor.execute(() -> instPortRemoved(instPort));
+ if (osPort != null) {
+ setPortBlockRules(instPort, false);
+ }
+
break;
case OPENSTACK_INSTANCE_MIGRATION_STARTED:
log.info("SwitchingHandler: Migration started for MAC:{} IP:{}",
@@ -640,6 +699,11 @@
eventExecutor.execute(() -> instPortDetected(instPort));
+ if (osPort != null) {
+ eventExecutor.execute(() ->
+ setPortBlockRules(instPort, !osPort.isAdminStateUp()));
+ }
+
break;
case OPENSTACK_INSTANCE_MIGRATION_ENDED:
log.info("SwitchingHandler: Migration finished for MAC:{} IP:{}",
@@ -665,4 +729,60 @@
// TODO add something else if needed
}
}
+
+ private class InternalOpenstackNetworkListener implements OpenstackNetworkListener {
+
+ @Override
+ public boolean isRelevant(OpenstackNetworkEvent event) {
+
+ // do not allow to proceed without leadership
+ NodeId leader = leadershipService.getLeader(appId.name());
+ return Objects.equals(localNodeId, leader);
+ }
+
+ @Override
+ public void event(OpenstackNetworkEvent event) {
+
+ if (event.subject() == null || event.port() == null) {
+ return;
+ }
+
+ boolean isNwAdminStateUp = event.subject().isAdminStateUp();
+ boolean isPortAdminStateUp = event.port().isAdminStateUp();
+
+ InstancePort instPort = instancePortService.instancePort(event.port().getId());
+
+ switch (event.type()) {
+ case OPENSTACK_NETWORK_CREATED:
+ case OPENSTACK_NETWORK_UPDATED:
+ eventExecutor.execute(() ->
+ setNetworkBlockRules(event.subject(), !isNwAdminStateUp));
+
+ break;
+ case OPENSTACK_NETWORK_REMOVED:
+ eventExecutor.execute(() ->
+ setNetworkBlockRules(event.subject(), false));
+ break;
+ case OPENSTACK_PORT_CREATED:
+ case OPENSTACK_PORT_UPDATED:
+
+ if (instPort != null) {
+ eventExecutor.execute(() ->
+ setPortBlockRules(instPort, !isPortAdminStateUp));
+ }
+
+ break;
+ case OPENSTACK_PORT_REMOVED:
+
+ if (instPort != null) {
+ eventExecutor.execute(() ->
+ setPortBlockRules(instPort, false));
+ }
+
+ break;
+ default:
+ break;
+ }
+ }
+ }
}