[ONOS-5176] Refactoring: improves SONA pipeline and OpenstackRoutingManager
Change-Id: I6e582fff781c2e69fb6ef4b34d8e41767202fc20
diff --git a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/AbstractVmHandler.java b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/AbstractVmHandler.java
index 58b89a6..a373ff0 100644
--- a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/AbstractVmHandler.java
+++ b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/AbstractVmHandler.java
@@ -25,6 +25,9 @@
import org.onosproject.net.host.HostEvent;
import org.onosproject.net.host.HostListener;
import org.onosproject.net.host.HostService;
+import org.onosproject.openstackinterface.OpenstackInterfaceService;
+import org.onosproject.openstackinterface.OpenstackRouter;
+import org.onosproject.openstackinterface.OpenstackSubnet;
import org.slf4j.Logger;
import java.util.Objects;
@@ -50,6 +53,7 @@
protected CoreService coreService;
protected MastershipService mastershipService;
protected HostService hostService;
+ protected OpenstackInterfaceService openstackService;
protected HostListener hostListener = new InternalHostListener();
@@ -57,6 +61,7 @@
ServiceDirectory services = new DefaultServiceDirectory();
coreService = services.get(CoreService.class);
mastershipService = services.get(MastershipService.class);
+ openstackService = services.get(OpenstackInterfaceService.class);
hostService = services.get(HostService.class);
hostService.addListener(hostListener);
@@ -107,6 +112,28 @@
.findFirst();
}
+ protected Set<Host> getHosts(OpenstackSubnet osSubnet) {
+ return Tools.stream(hostService.getHosts())
+ .filter(host -> host.annotations().value(SUBNET_ID).equals(osSubnet.id()))
+ .collect(Collectors.toSet());
+ }
+
+ protected Optional<OpenstackRouter> getRouter(Host host) {
+ return openstackService.routers().stream()
+ .filter(router -> routableSubNets(router.id()).stream()
+ .filter(subnet -> subnet.id().equals(host.annotations().value(SUBNET_ID)))
+ .findAny().isPresent())
+ .findAny();
+ }
+
+ protected Set<OpenstackSubnet> routableSubNets(String osRouterId) {
+ return openstackService.ports().stream()
+ .filter(p -> p.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE) &&
+ p.deviceId().equals(osRouterId))
+ .map(p -> openstackService.subnet(p.fixedIps().keySet().stream().findFirst().get()))
+ .collect(Collectors.toSet());
+ }
+
protected Ip4Address getIp(Host host) {
return host.ipAddresses().stream().findFirst().get().getIp4Address();
}
diff --git a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/RulePopulatorUtil.java b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/RulePopulatorUtil.java
index d220b8c..3326417 100644
--- a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/RulePopulatorUtil.java
+++ b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/RulePopulatorUtil.java
@@ -21,8 +21,8 @@
import org.onosproject.net.DeviceId;
import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.instructions.ExtensionPropertyException;
import org.onosproject.net.flow.instructions.ExtensionTreatment;
import org.onosproject.net.flowobjective.DefaultForwardingObjective;
@@ -74,29 +74,36 @@
}
/**
- * Removes flow rules with the supplied information.
+ * Adds flow rules with the supplied information.
*
* @param flowObjectiveService flow objective service
* @param appId application id
* @param deviceId device id to remove this flow rule
* @param selector traffic selector
+ * @param treatment traffic treatment
* @param flag flag
* @param priority priority
+ * @param install populate flows if true, remove them otherwise
*/
- public static void removeRule(FlowObjectiveService flowObjectiveService,
- ApplicationId appId,
- DeviceId deviceId,
- TrafficSelector selector,
- ForwardingObjective.Flag flag,
- int priority) {
- ForwardingObjective fo = DefaultForwardingObjective.builder()
+ public static void setRule(FlowObjectiveService flowObjectiveService,
+ ApplicationId appId,
+ DeviceId deviceId,
+ TrafficSelector selector,
+ TrafficTreatment treatment,
+ ForwardingObjective.Flag flag,
+ int priority,
+ boolean install) {
+ ForwardingObjective.Builder foBuilder = DefaultForwardingObjective.builder()
.withSelector(selector)
- .withTreatment(DefaultTrafficTreatment.builder().build())
+ .withTreatment(treatment)
.withFlag(flag)
.withPriority(priority)
- .fromApp(appId)
- .remove();
+ .fromApp(appId);
- flowObjectiveService.forward(deviceId, fo);
+ if (install) {
+ flowObjectiveService.forward(deviceId, foBuilder.add());
+ } else {
+ flowObjectiveService.forward(deviceId, foBuilder.remove());
+ }
}
}
diff --git a/apps/openstacknetworking/routing/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackFloatingIpManager.java b/apps/openstacknetworking/routing/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackFloatingIpManager.java
index b3990e1..7b7f778 100644
--- a/apps/openstacknetworking/routing/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackFloatingIpManager.java
+++ b/apps/openstacknetworking/routing/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackFloatingIpManager.java
@@ -263,29 +263,32 @@
.matchIPDst(floatingIp.toIpPrefix())
.matchInPort(nodeService.tunnelPort(deviceId).get());
- RulePopulatorUtil.removeRule(
+ RulePopulatorUtil.setRule(
flowObjectiveService,
appId,
deviceId,
sOutgoingBuilder.build(),
+ DefaultTrafficTreatment.builder().build(),
ForwardingObjective.Flag.VERSATILE,
- FLOATING_RULE_PRIORITY);
+ FLOATING_RULE_PRIORITY, false);
- RulePopulatorUtil.removeRule(
+ RulePopulatorUtil.setRule(
flowObjectiveService,
appId,
deviceId,
sIncomingBuilder.build(),
+ DefaultTrafficTreatment.builder().build(),
ForwardingObjective.Flag.VERSATILE,
- FLOATING_RULE_PRIORITY);
+ FLOATING_RULE_PRIORITY, false);
- RulePopulatorUtil.removeRule(
+ RulePopulatorUtil.setRule(
flowObjectiveService,
appId,
deviceId,
sForTrafficFromVmBuilder.build(),
+ DefaultTrafficTreatment.builder().build(),
ForwardingObjective.Flag.VERSATILE,
- FLOATING_RULE_FOR_TRAFFIC_FROM_VM_PRIORITY);
+ FLOATING_RULE_FOR_TRAFFIC_FROM_VM_PRIORITY, false);
});
}
diff --git a/apps/openstacknetworking/routing/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingManager.java b/apps/openstacknetworking/routing/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingManager.java
index c8ce876..f7989bd 100644
--- a/apps/openstacknetworking/routing/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingManager.java
+++ b/apps/openstacknetworking/routing/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingManager.java
@@ -15,7 +15,6 @@
*/
package org.onosproject.openstacknetworking.routing;
-import com.google.common.collect.ImmutableSet;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
@@ -25,10 +24,11 @@
import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv4;
import org.onlab.packet.Ip4Address;
+import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
import org.onlab.util.Tools;
import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
import org.onosproject.core.GroupId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
@@ -38,12 +38,10 @@
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flowobjective.DefaultForwardingObjective;
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.openstackinterface.OpenstackInterfaceService;
import org.onosproject.openstackinterface.OpenstackNetwork;
-import org.onosproject.openstackinterface.OpenstackPort;
import org.onosproject.openstackinterface.OpenstackRouter;
import org.onosproject.openstackinterface.OpenstackRouterInterface;
import org.onosproject.openstackinterface.OpenstackSubnet;
@@ -62,7 +60,6 @@
import java.util.HashMap;
import java.util.Map;
-import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ExecutorService;
@@ -85,9 +82,6 @@
protected FlowObjectiveService flowObjectiveService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected DeviceService deviceService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected OpenstackInterfaceService openstackService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -96,6 +90,12 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ScalableGatewayService gatewayService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CoreService coreService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DeviceService deviceService;
+
private final ExecutorService eventExecutor = newSingleThreadScheduledExecutor(
groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
private final InternalNodeListener nodeListener = new InternalNodeListener();
@@ -111,37 +111,56 @@
@Deactivate
protected void deactivate() {
+ super.deactivate();
nodeService.removeListener(nodeListener);
log.info("stopped");
}
@Override
+ protected void hostDetected(Host host) {
+ // Installs forwarding flow rules to VMs in different nodes and different subnets
+ // that are connected via a router
+ Optional<OpenstackRouter> routerOfTheHost = getRouter(host);
+
+ if (!routerOfTheHost.isPresent()) {
+ return;
+ }
+
+ routableSubNets(routerOfTheHost.get().id()).stream()
+ .filter(subnet -> !subnet.id().equals(host.annotations().value(SUBNET_ID)))
+ .forEach(subnet -> setForwardingRulesAmongHostsInDifferentCnodes(host, getHosts(subnet), true));
+ }
+
+ @Override
+ protected void hostRemoved(Host host) {
+ // Removes forwarding flow rules to VMs in different nodes and different subnets
+ // that are connected via a router
+ Optional<OpenstackRouter> routerOfTheHost = getRouter(host);
+ if (!routerOfTheHost.isPresent()) {
+ return;
+ }
+
+ routableSubNets(routerOfTheHost.get().id()).stream()
+ .filter(subnet -> !subnet.id().equals(host.annotations().value(SUBNET_ID)))
+ .forEach(subnet -> setForwardingRulesAmongHostsInDifferentCnodes(host, getHosts(subnet), false));
+ }
+
+ @Override
public void createRouter(OpenstackRouter osRouter) {
}
@Override
public void updateRouter(OpenstackRouter osRouter) {
if (osRouter.gatewayExternalInfo().externalFixedIps().size() > 0) {
- openstackService.ports().stream()
- .filter(osPort -> osPort.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE) &&
- osPort.deviceId().equals(osRouter.id()))
- .forEach(osPort -> {
- String subnetId = osPort.fixedIps().keySet().stream().findFirst().get();
- setExternalConnection(osRouter, subnetId);
- });
+ routableSubNets(osRouter.id()).stream()
+ .forEach(subnet -> setExternalConnection(osRouter, subnet, true));
log.info("Connected external gateway {} to router {}",
osRouter.gatewayExternalInfo().externalFixedIps(),
osRouter.name());
} else {
- openstackService.ports().stream()
- .filter(osPort -> osPort.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE) &&
- osPort.deviceId().equals(osRouter.id()))
- .forEach(osPort -> {
- String subnetId = osPort.fixedIps().keySet().stream().findFirst().get();
- OpenstackSubnet osSubNet = openstackService.subnet(subnetId);
- unsetExternalConnection(osRouter, osPort.networkId(), osSubNet.cidr());
- });
+ routableSubNets(osRouter.id()).stream()
+ .forEach(subnet -> setExternalConnection(osRouter, subnet, false));
log.info("Disconnected external gateway from router {}",
osRouter.name());
@@ -150,309 +169,163 @@
@Override
public void removeRouter(String osRouterId) {
- // TODO implement this
+ // Nothing to do
+ // All interfaces need to be removed before the router is removed,
+ // and all related flow rues are removed when the interfaces are removed.
}
@Override
- public void addRouterInterface(OpenstackRouterInterface routerIface) {
- OpenstackRouter osRouter = openstackRouter(routerIface.id());
- OpenstackPort osPort = openstackService.port(routerIface.portId());
- if (osRouter == null || osPort == null) {
- log.warn("Failed to add router interface {}", routerIface);
+ public void addRouterInterface(OpenstackRouterInterface routerIfaceAdded) {
+ OpenstackRouter osRouter = openstackRouter(routerIfaceAdded.id());
+ OpenstackSubnet osSubnetAdded = openstackService.subnet(routerIfaceAdded.subnetId());
+ if (osRouter == null || osSubnetAdded == null) {
+ log.warn("Failed to add router interface {}", routerIfaceAdded);
return;
}
-
- setGatewayIcmp(Ip4Address.valueOf(openstackService.subnet(routerIface.subnetId()).gatewayIp()));
-
- setRoutes(osRouter, Optional.empty());
- if (osRouter.gatewayExternalInfo().externalFixedIps().size() > 0) {
- String subnetId = osPort.fixedIps().keySet().stream().findFirst().get();
- setExternalConnection(osRouter, subnetId);
- }
- log.info("Connected {} to router {}", osPort.fixedIps(), osRouter.name());
+ handleRouterInterfaces(osRouter, osSubnetAdded);
}
@Override
public void removeRouterInterface(OpenstackRouterInterface routerIface) {
OpenstackRouter osRouter = openstackService.router(routerIface.id());
+ OpenstackSubnet osSubnetRemoved = openstackService.subnet(routerIface.subnetId());
if (osRouter == null) {
log.warn("Failed to remove router interface {}", routerIface);
return;
}
+ handleRouterInterfacesRemoved(osRouter, osSubnetRemoved);
- OpenstackSubnet osSubnet = openstackService.subnet(routerIface.subnetId());
- OpenstackNetwork osNet = openstackService.network(osSubnet.networkId());
+ log.info("Disconnected {} from router {}", osSubnetRemoved.cidr(), osRouter.name());
+ }
- unsetGatewayIcmp(Ip4Address.valueOf(openstackService.subnet(routerIface.subnetId()).gatewayIp()));
+ private void handleRouterInterfaces(OpenstackRouter osRouter, OpenstackSubnet osSubnetAdded) {
+ OpenstackNetwork osNetworkAdded = openstackService.network(osSubnetAdded.networkId());
+ if (osNetworkAdded == null) { // in case of external network subnet
+ return;
+ }
- unsetRoutes(osRouter, osSubnet);
+ // Sets flow rules for routing among subnets connected to a router.
+ setRoutesAmongSubnets(osRouter, osSubnetAdded, true);
+ // Sets flow rules for forwarding "packets going to external networks" to gateway nodes.
if (osRouter.gatewayExternalInfo().externalFixedIps().size() > 0) {
- unsetExternalConnection(osRouter, osNet.id(), osSubnet.cidr());
- }
- log.info("Disconnected {} from router {}", osSubnet.cidr(), osRouter.name());
- }
-
- private void setGatewayIcmp(Ip4Address gatewayIp) {
- if (gatewayIp == null) {
- return;
- }
- gatewayService.getGatewayDeviceIds().forEach(deviceId -> populateGatewayIcmpRule(gatewayIp, deviceId));
- }
-
- private void populateGatewayIcmpRule(Ip4Address gatewayIp, DeviceId deviceId) {
- TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-
- sBuilder.matchEthType(Ethernet.TYPE_IPV4)
- .matchIPProtocol(IPv4.PROTOCOL_ICMP)
- .matchIPDst(gatewayIp.toIpPrefix());
-
- tBuilder.setOutput(PortNumber.CONTROLLER);
-
- ForwardingObjective fo = DefaultForwardingObjective.builder()
- .withSelector(sBuilder.build())
- .withTreatment(tBuilder.build())
- .withPriority(GATEWAY_ICMP_PRIORITY)
- .withFlag(ForwardingObjective.Flag.VERSATILE)
- .fromApp(appId)
- .add();
-
- flowObjectiveService.forward(deviceId, fo);
- }
-
- private void unsetGatewayIcmp(Ip4Address gatewayIp) {
- if (gatewayIp == null) {
- return;
- }
- gatewayService.getGatewayDeviceIds().forEach(deviceId -> {
- removeGatewayIcmpRule(gatewayIp, deviceId);
- });
- }
-
- private void removeGatewayIcmpRule(Ip4Address gatewayIp, DeviceId deviceId) {
- TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
-
- sBuilder.matchEthType(Ethernet.TYPE_IPV4)
- .matchIPProtocol(IPv4.PROTOCOL_ICMP)
- .matchIPDst(gatewayIp.toIpPrefix());
-
- RulePopulatorUtil.removeRule(flowObjectiveService, appId, deviceId, sBuilder.build(),
- ForwardingObjective.Flag.VERSATILE, GATEWAY_ICMP_PRIORITY);
-
- }
- private void setExternalConnection(OpenstackRouter osRouter, String osSubNetId) {
- if (!osRouter.gatewayExternalInfo().isEnablePnat()) {
- log.debug("Source NAT is disabled");
- return;
+ setExternalConnection(osRouter, osSubnetAdded, true);
}
- OpenstackSubnet osSubNet = openstackService.subnet(osSubNetId);
- OpenstackNetwork osNet = openstackService.network(osSubNet.networkId());
- populateExternalRules(osNet, osSubNet);
+ // Sets flow rules to handle ping to the virtual gateway.
+ Ip4Address vGatewayIp = Ip4Address.valueOf(osSubnetAdded.gatewayIp());
+ gatewayService.getGatewayDeviceIds()
+ .forEach(deviceId -> setGatewayIcmpRule(vGatewayIp, deviceId, true));
+
+ // Sets east-west routing rules for VMs in different Cnode to Switching Table.
+ setForwardingRulesForEastWestRouting(osRouter, osSubnetAdded, true);
+
}
- private void unsetExternalConnection(OpenstackRouter osRouter, String osNetId, String subNetCidr) {
- if (!osRouter.gatewayExternalInfo().isEnablePnat()) {
- log.debug("Source NAT is disabled");
- return;
+ private void handleRouterInterfacesRemoved(OpenstackRouter osRouter, OpenstackSubnet osSubnetRemoved) {
+
+ // Removes flow rules for routing among subnets connected to a router.
+ setRoutesAmongSubnets(osRouter, osSubnetRemoved, false);
+
+ // Removes flow rules for forwarding "packets going to external networks" to gateway nodes.
+ if (osRouter.gatewayExternalInfo().externalFixedIps().size() > 0) {
+ setExternalConnection(osRouter, osSubnetRemoved, false);
}
- // FIXME router interface is subnet specific, not network
- OpenstackNetwork osNet = openstackService.network(osNetId);
- removeExternalRules(osNet, subNetCidr);
+ // Removes flow rules to handle ping to the virtual gateway.
+ Ip4Address vGatewayIp = Ip4Address.valueOf(osSubnetRemoved.gatewayIp());
+ gatewayService.getGatewayDeviceIds()
+ .forEach(deviceId -> setGatewayIcmpRule(vGatewayIp, deviceId, false));
+
+ // Removes east-west routing rules for VMs in different Cnode to Switching Table.
+ setForwardingRulesForEastWestRouting(osRouter, osSubnetRemoved, false);
+
+ // Resets east-west routing rules for VMs in different Cnode to Switching Table.
+ routableSubNets(osRouter.id()).stream()
+ .forEach(subnet -> setForwardingRulesForEastWestRouting(osRouter, subnet, true));
}
- private void setRoutes(OpenstackRouter osRouter, Optional<Host> host) {
+ private void setRoutesAmongSubnets(OpenstackRouter osRouter, OpenstackSubnet osSubnetAdded, boolean install) {
Set<OpenstackSubnet> routableSubNets = routableSubNets(osRouter.id());
if (routableSubNets.size() < 2) {
// no other subnet interface is connected to this router, do nothing
return;
}
- Set<String> routableSubNetIds = routableSubNets.stream()
- .map(OpenstackSubnet::id)
- .collect(Collectors.toSet());
-
- if (host.isPresent()) {
- if (!routableSubNetIds.contains(host.get().annotations().value(SUBNET_ID))) {
- // subnet of host is not connected to this router, do nothing.
- return;
- }
- }
-
- Set<Host> hosts = host.isPresent() ? ImmutableSet.of(host.get()) :
- Tools.stream(hostService.getHosts())
- .filter(h -> routableSubNetIds.contains(h.annotations().value(SUBNET_ID)))
- .collect(Collectors.toSet());
-
- hosts.forEach(h -> populateRoutingRules(h, routableSubNets));
- }
-
- private void unsetRoutes(OpenstackRouter osRouter, OpenstackSubnet osSubNet) {
- Set<OpenstackSubnet> routableSubNets = routableSubNets(osRouter.id());
- Tools.stream(hostService.getHosts())
- .filter(h -> Objects.equals(
- h.annotations().value(NETWORK_ID), osSubNet.id()))
- .forEach(h -> removeRoutingRules(h, routableSubNets));
-
- routableSubNets.forEach(n -> {
- Tools.stream(hostService.getHosts())
- .filter(h -> Objects.equals(
- h.annotations().value(SUBNET_ID),
- n.id()))
- .forEach(h -> removeRoutingRules(h, ImmutableSet.of(osSubNet)));
- log.debug("Removed between {} to {}", n.name(), osSubNet.name());
- });
- }
-
- private OpenstackRouter openstackRouter(String routerId) {
- return openstackService.routers().stream().filter(r ->
- r.id().equals(routerId)).iterator().next();
- }
-
- private Optional<OpenstackPort> routerIfacePort(String osNetId, String osSubNetId) {
- // FIXME router interface is subnet specific, not network
- return openstackService.ports().stream()
- .filter(p -> p.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE) &&
- p.networkId().equals(osNetId) &&
- p.fixedIps().containsKey(osSubNetId))
- .findAny();
- }
-
- private Set<OpenstackSubnet> routableSubNets(String osRouterId) {
- return openstackService.ports().stream()
- .filter(p -> p.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE) &&
- p.deviceId().equals(osRouterId))
- .map(p -> openstackService.subnet(p.fixedIps().keySet().stream().findFirst().get()))
- .collect(Collectors.toSet());
- }
-
- private void populateExternalRules(OpenstackNetwork osNet, OpenstackSubnet osSubNet) {
- populateCnodeToGateway(Long.valueOf(osNet.segmentId()), osSubNet.cidr());
- populateGatewayToController(Long.valueOf(osNet.segmentId()), osSubNet.cidr());
- }
-
- private void removeExternalRules(OpenstackNetwork osNet, String subNetCidr) {
- TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
- sBuilder.matchEthType(Ethernet.TYPE_IPV4)
- .matchTunnelId(Long.valueOf(osNet.segmentId()))
- .matchIPSrc(IpPrefix.valueOf(subNetCidr))
- .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
-
- nodeService.completeNodes().forEach(node -> {
- ForwardingObjective.Flag flag = node.type().equals(GATEWAY) ?
- ForwardingObjective.Flag.VERSATILE :
- ForwardingObjective.Flag.SPECIFIC;
-
- RulePopulatorUtil.removeRule(
- flowObjectiveService,
- appId,
- node.intBridge(),
- sBuilder.build(),
- flag,
- ROUTING_RULE_PRIORITY);
- });
- }
-
- private void populateRoutingRules(Host host, Set<OpenstackSubnet> osSubNets) {
- String osSubNetId = host.annotations().value(SUBNET_ID);
- if (osSubNetId == null) {
- return;
- }
-
- DeviceId localDevice = host.location().deviceId();
- PortNumber localPort = host.location().port();
- if (!nodeService.dataIp(localDevice).isPresent()) {
- log.warn("Failed to populate L3 rules");
- return;
- }
-
Map<String, String> vniMap = new HashMap<>();
openstackService.networks().forEach(n -> vniMap.put(n.id(), n.segmentId()));
- // TODO improve pipeline, do we have to install access rules between networks
- // for every single VMs?
- osSubNets.stream().filter(osSubNet -> !osSubNet.id().equals(osSubNetId)).forEach(osSubNet -> {
- populateRoutingRulestoSameNode(
- host.ipAddresses().stream().findFirst().get().getIp4Address(),
- host.mac(),
- localPort, localDevice,
- Long.valueOf(vniMap.get(osSubNet.networkId())),
- osSubNet.cidr());
-
- nodeService.completeNodes().stream()
- .filter(node -> node.type().equals(COMPUTE))
- .filter(node -> !node.intBridge().equals(localDevice))
- .forEach(node -> populateRoutingRulestoDifferentNode(
- host.ipAddresses().stream().findFirst().get().getIp4Address(),
- Long.valueOf(vniMap.get(osSubNet.networkId())),
- node.intBridge(),
- nodeService.dataIp(localDevice).get().getIp4Address(),
- osSubNet.cidr()));
- });
+ routableSubNets.stream()
+ .filter(subnet -> !subnet.id().equals(osSubnetAdded.id()))
+ .filter(subnet -> vniMap.get(subnet.networkId()) != null)
+ .forEach(subnet -> nodeService.completeNodes().stream()
+ .filter(node -> node.type().equals(COMPUTE))
+ .forEach(node -> {
+ setRoutingRules(node.intBridge(),
+ Integer.parseInt(vniMap.get(subnet.networkId())),
+ Integer.parseInt(vniMap.get(osSubnetAdded.networkId())),
+ subnet, osSubnetAdded, install);
+ setRoutingRules(node.intBridge(),
+ Integer.parseInt(vniMap.get(osSubnetAdded.networkId())),
+ Integer.parseInt(vniMap.get(subnet.networkId())),
+ osSubnetAdded, subnet, install);
+ }
+ ));
}
- private void removeRoutingRules(Host host, Set<OpenstackSubnet> osSubNets) {
- String osSubNetId = host.annotations().value(SUBNET_ID);
- if (osSubNetId == null) {
- return;
- }
+ private void setRoutingRules(DeviceId deviceId, int srcVni, int dstVni,
+ OpenstackSubnet subnetSrc, OpenstackSubnet subnetDst, boolean install) {
- Map<String, String> vniMap = new HashMap<>();
- openstackService.networks().forEach(n -> vniMap.put(n.id(), n.segmentId()));
-
- osSubNets.stream().filter(osSubNet -> !osSubNet.id().equals(osSubNetId)).forEach(osSubNet -> {
- TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
- sBuilder.matchEthType(Ethernet.TYPE_IPV4)
- .matchIPDst(host.ipAddresses().stream().findFirst().get().toIpPrefix())
- .matchIPSrc(IpPrefix.valueOf(osSubNet.cidr()))
- .matchTunnelId(Long.valueOf(vniMap.get(osSubNet.networkId())));
-
- nodeService.completeNodes().stream()
- .filter(node -> node.type().equals(COMPUTE))
- .forEach(node -> RulePopulatorUtil.removeRule(
- flowObjectiveService,
- appId,
- node.intBridge(),
- sBuilder.build(),
- ForwardingObjective.Flag.SPECIFIC,
- EW_ROUTING_RULE_PRIORITY));
- });
- log.debug("Removed routing rule from {} to {}", host, osSubNets);
- }
-
- private void populateGatewayToController(long vni, String subNetCidr) {
TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
sBuilder.matchEthType(Ethernet.TYPE_IPV4)
- .matchTunnelId(vni)
- .matchIPSrc(IpPrefix.valueOf(subNetCidr))
- .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
- tBuilder.setOutput(PortNumber.CONTROLLER);
+ .matchTunnelId(srcVni)
+ .matchIPSrc(IpPrefix.valueOf(subnetSrc.cidr()))
+ .matchIPDst(IpPrefix.valueOf(subnetDst.cidr()));
- ForwardingObjective fo = DefaultForwardingObjective.builder()
- .withSelector(sBuilder.build())
- .withTreatment(tBuilder.build())
- .withFlag(ForwardingObjective.Flag.VERSATILE)
- .withPriority(ROUTING_RULE_PRIORITY)
- .fromApp(appId)
- .add();
+ tBuilder.setTunnelId(dstVni);
- gatewayService.getGatewayDeviceIds().forEach(deviceId -> flowObjectiveService.forward(deviceId, fo));
+ RulePopulatorUtil.setRule(flowObjectiveService, appId, deviceId, sBuilder.build(),
+ tBuilder.build(), ForwardingObjective.Flag.SPECIFIC, EW_ROUTING_RULE_PRIORITY, install);
+
+ // Flow rules for destination is in different subnet and different node,
+ // because VNI is converted to destination VNI in the source VM node.
+ sBuilder = DefaultTrafficSelector.builder();
+ tBuilder = DefaultTrafficTreatment.builder();
+
+ sBuilder.matchEthType(Ethernet.TYPE_IPV4)
+ .matchTunnelId(dstVni)
+ .matchIPSrc(IpPrefix.valueOf(subnetSrc.cidr()))
+ .matchIPDst(IpPrefix.valueOf(subnetDst.cidr()));
+
+ tBuilder.setTunnelId(dstVni);
+
+ RulePopulatorUtil.setRule(flowObjectiveService, appId, deviceId, sBuilder.build(),
+ tBuilder.build(), ForwardingObjective.Flag.SPECIFIC, EW_ROUTING_RULE_PRIORITY, install);
}
- private void populateCnodeToGateway(long vni, String subnetCidr) {
+ private void setExternalConnection(OpenstackRouter osRouter, OpenstackSubnet osSubNet, boolean install) {
+ if (!osRouter.gatewayExternalInfo().isEnablePnat()) {
+ log.debug("Source NAT is disabled");
+ return;
+ }
+
+ //OpenstackSubnet osSubNet = openstackService.subnet(osSubNetId);
+ OpenstackNetwork osNet = openstackService.network(osSubNet.networkId());
+
nodeService.completeNodes().stream()
.filter(node -> node.type().equals(COMPUTE))
- .forEach(node -> populateRuleToGateway(
+ .forEach(node -> setRulesToGateway(
node.intBridge(),
gatewayService.getGatewayGroupId(node.intBridge()),
- vni, subnetCidr));
+ Long.valueOf(osNet.segmentId()), osSubNet.cidr(), install));
+
+ // Is this for PNAT ??
+ setRulesForGatewayToController(Long.valueOf(osNet.segmentId()), osSubNet.cidr(), install);
}
- private void populateRuleToGateway(DeviceId deviceId, GroupId groupId, long vni, String cidr) {
+ private void setRulesToGateway(DeviceId deviceId, GroupId groupId, long vni, String cidr, boolean install) {
TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
@@ -462,133 +335,119 @@
.matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
tBuilder.group(groupId);
- ForwardingObjective fo = DefaultForwardingObjective.builder()
- .withSelector(sBuilder.build())
- .withTreatment(tBuilder.build())
- .withFlag(ForwardingObjective.Flag.SPECIFIC)
- .withPriority(ROUTING_RULE_PRIORITY)
- .fromApp(appId)
- .add();
- flowObjectiveService.forward(deviceId, fo);
+ RulePopulatorUtil.setRule(flowObjectiveService, appId, deviceId, sBuilder.build(),
+ tBuilder.build(), ForwardingObjective.Flag.SPECIFIC, ROUTING_RULE_PRIORITY, install);
}
- private void populateRoutingRulestoDifferentNode(Ip4Address vmIp, long vni,
- DeviceId deviceId, Ip4Address hostIp,
- String cidr) {
+ private void setRulesForGatewayToController(long vni, String subNetCidr, boolean install) {
TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
sBuilder.matchEthType(Ethernet.TYPE_IPV4)
.matchTunnelId(vni)
- .matchIPSrc(IpPrefix.valueOf(cidr))
- .matchIPDst(vmIp.toIpPrefix());
- tBuilder.extension(buildExtension(deviceService, deviceId, hostIp), deviceId)
- .setOutput(nodeService.tunnelPort(deviceId).get());
+ .matchIPSrc(IpPrefix.valueOf(subNetCidr))
+ .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
+ tBuilder.setOutput(PortNumber.CONTROLLER);
- ForwardingObjective fo = DefaultForwardingObjective.builder()
- .withSelector(sBuilder.build())
- .withTreatment(tBuilder.build())
- .withPriority(EW_ROUTING_RULE_PRIORITY)
- .withFlag(ForwardingObjective.Flag.SPECIFIC)
- .fromApp(appId)
- .add();
-
- flowObjectiveService.forward(deviceId, fo);
+ gatewayService.getGatewayDeviceIds().forEach(deviceId ->
+ RulePopulatorUtil.setRule(flowObjectiveService, appId, deviceId, sBuilder.build(),
+ tBuilder.build(), ForwardingObjective.Flag.VERSATILE, ROUTING_RULE_PRIORITY, install));
}
- private void populateRoutingRulestoSameNode(Ip4Address vmIp, MacAddress vmMac,
- PortNumber port, DeviceId deviceId, long vni,
- String cidr) {
+ private void setGatewayIcmpRule(Ip4Address gatewayIp, DeviceId deviceId, boolean install) {
TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
- // FIXME: we need to check the VNI of the dest IP also just in case...
sBuilder.matchEthType(Ethernet.TYPE_IPV4)
- .matchIPDst(vmIp.toIpPrefix())
- .matchIPSrc(IpPrefix.valueOf(cidr))
- .matchTunnelId(vni);
+ .matchIPProtocol(IPv4.PROTOCOL_ICMP)
+ .matchIPDst(gatewayIp.toIpPrefix());
- tBuilder.setEthDst(vmMac)
- .setOutput(port);
+ tBuilder.setOutput(PortNumber.CONTROLLER);
- ForwardingObjective fo = DefaultForwardingObjective.builder()
- .withSelector(sBuilder.build())
- .withTreatment(tBuilder.build())
- .withPriority(EW_ROUTING_RULE_PRIORITY)
- .withFlag(ForwardingObjective.Flag.SPECIFIC)
- .fromApp(appId)
- .add();
-
- flowObjectiveService.forward(deviceId, fo);
+ RulePopulatorUtil.setRule(flowObjectiveService, appId, deviceId, sBuilder.build(),
+ tBuilder.build(), ForwardingObjective.Flag.VERSATILE, GATEWAY_ICMP_PRIORITY, install);
}
- private void reloadRoutingRules() {
- eventExecutor.execute(() -> openstackService.ports().stream()
- .filter(osPort -> osPort.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE))
- .forEach(osPort -> {
- OpenstackRouter osRouter = openstackRouter(osPort.deviceId());
+ private void setForwardingRulesForEastWestRouting(OpenstackRouter router, OpenstackSubnet subnetAdded,
+ boolean install) {
- setGatewayIcmp(Ip4Address.valueOf(openstackService
- .subnet(osPort.fixedIps().keySet().stream().findAny().get()).gatewayIp()));
+ Set<OpenstackSubnet> subnets = routableSubNets(router.id());
- setRoutes(osRouter, Optional.empty());
- if (osRouter.gatewayExternalInfo().externalFixedIps().size() > 0) {
- String subnetId = osPort.fixedIps().keySet().stream().findFirst().get();
- setExternalConnection(osRouter, subnetId);
+ Set<Host> hosts = Tools.stream(hostService.getHosts())
+ .filter(h -> getVni(h).equals(openstackService.network(subnetAdded.networkId()).segmentId()))
+ .collect(Collectors.toSet());
+
+ subnets.stream()
+ .filter(subnet -> !subnet.id().equals(subnetAdded.id()))
+ .forEach(subnet -> getHosts(subnet)
+ .forEach(h -> setForwardingRulesAmongHostsInDifferentCnodes(h, hosts, install)));
+ }
+
+ private void setForwardingRulesAmongHostsInDifferentCnodes(Host host, Set<Host> remoteHosts, boolean install) {
+ Ip4Address localVmIp = getIp(host);
+ DeviceId localDeviceId = host.location().deviceId();
+ Optional<IpAddress> localDataIp = nodeService.dataIp(localDeviceId);
+
+ if (!localDataIp.isPresent()) {
+ log.debug("Failed to get data IP for device {}",
+ host.location().deviceId());
+ return;
+ }
+
+ remoteHosts.stream()
+ .filter(remoteHost -> !host.location().deviceId().equals(remoteHost.location().deviceId()))
+ .forEach(remoteVm -> {
+ Optional<IpAddress> remoteDataIp = nodeService.dataIp(remoteVm.location().deviceId());
+ if (remoteDataIp.isPresent()) {
+ setVxLanFlowRule(getVni(remoteVm),
+ localDeviceId,
+ remoteDataIp.get().getIp4Address(),
+ getIp(remoteVm), install);
+
+ setVxLanFlowRule(getVni(host),
+ remoteVm.location().deviceId(),
+ localDataIp.get().getIp4Address(),
+ localVmIp, install);
}
- }));
+ });
}
- @Override
- protected void hostDetected(Host host) {
- String osNetId = host.annotations().value(NETWORK_ID);
- String osSubNetId = host.annotations().value(SUBNET_ID);
- Optional<OpenstackPort> routerIface = routerIfacePort(osNetId, osSubNetId);
- if (!routerIface.isPresent()) {
+ private void setVxLanFlowRule(String vni, DeviceId deviceId, Ip4Address remoteIp,
+ Ip4Address vmIp, boolean install) {
+ Optional<PortNumber> tunnelPort = nodeService.tunnelPort(deviceId);
+ if (!tunnelPort.isPresent()) {
+ log.warn("Failed to get tunnel port from {}", deviceId);
return;
}
- eventExecutor.execute(() -> setRoutes(
- openstackRouter(routerIface.get().deviceId()),
- Optional.of(host)));
+
+ TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
+
+ sBuilder.matchEthType(Ethernet.TYPE_IPV4)
+ .matchTunnelId(Long.parseLong(vni))
+ .matchIPDst(vmIp.toIpPrefix());
+ tBuilder.extension(buildExtension(deviceService, deviceId, remoteIp), deviceId)
+ .setOutput(tunnelPort.get());
+
+ RulePopulatorUtil.setRule(flowObjectiveService, appId, deviceId, sBuilder.build(),
+ tBuilder.build(), ForwardingObjective.Flag.SPECIFIC, SWITCHING_RULE_PRIORITY, install);
}
- @Override
- protected void hostRemoved(Host host) {
- String osNetId = host.annotations().value(NETWORK_ID);
- String osSubNetId = host.annotations().value(SUBNET_ID);
- Optional<OpenstackPort> routerIface = routerIfacePort(osNetId, osSubNetId);
- if (!routerIface.isPresent()) {
- return;
- }
- Set<OpenstackSubnet> routableSubNets = routableSubNets(routerIface.get().deviceId());
- eventExecutor.execute(() -> removeRoutingRules(host, routableSubNets));
+
+ private OpenstackRouter openstackRouter(String routerId) {
+ return openstackService.routers().stream().filter(r ->
+ r.id().equals(routerId)).iterator().next();
}
@Override
public void reinstallVmFlow(Host host) {
- if (host == null) {
- hostService.getHosts().forEach(h -> {
- hostDetected(h);
- log.info("Re-Install data plane flow of virtual machine {}", h);
- });
- } else {
- hostDetected(host);
- log.info("Re-Install data plane flow of virtual machine {}", host);
- }
+ // TODO: implements later
}
@Override
public void purgeVmFlow(Host host) {
- if (host == null) {
- hostService.getHosts().forEach(h -> {
- hostRemoved(h);
- log.info("Purge data plane flow of virtual machine {}", h);
- });
- } else {
- hostRemoved(host);
- log.info("Purge data plane flow of virtual machine {}", host);
- }
+ // TODO: implements later
}
private class InternalNodeListener implements OpenstackNodeListener {
@@ -599,6 +458,7 @@
switch (event.type()) {
case COMPLETE:
+ case INCOMPLETE:
log.info("COMPLETE node {} detected", node.hostname());
eventExecutor.execute(() -> {
if (node.type() == GATEWAY) {
@@ -609,23 +469,13 @@
.build();
gatewayService.addGatewayNode(gnode);
}
- reloadRoutingRules();
});
+ openstackService.routers().stream()
+ .forEach(router -> routableSubNets(router.id()).stream()
+ .forEach(subnet -> handleRouterInterfaces(router, subnet)));
break;
case INIT:
case DEVICE_CREATED:
- case INCOMPLETE:
- eventExecutor.execute(() -> {
- if (node.type() == GATEWAY) {
- GatewayNode gnode = GatewayNode.builder()
- .gatewayDeviceId(node.intBridge())
- .dataIpAddress(node.dataIp().getIp4Address())
- .uplinkIntf(node.externalPortName().get())
- .build();
- gatewayService.deleteGatewayNode(gnode);
- }
- reloadRoutingRules();
- });
default:
break;
}
diff --git a/apps/openstacknetworking/switching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSwitchingManager.java b/apps/openstacknetworking/switching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSwitchingManager.java
index db324d7..b66ffa2 100644
--- a/apps/openstacknetworking/switching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSwitchingManager.java
+++ b/apps/openstacknetworking/switching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSwitchingManager.java
@@ -119,7 +119,11 @@
.matchIPDst(getIp(host).toIpPrefix())
.matchTunnelId(Long.valueOf(getVni(host)));
- tBuilder.setOutput(host.location().port());
+ // Destination setting is required for routing cases.
+ // We do not believe the rule would not degrade the forwarding performance.
+ // But, if it does, we need to move the rule in a separate routing table.
+ tBuilder.setEthDst(host.mac())
+ .setOutput(host.location().port());
ForwardingObjective fo = DefaultForwardingObjective.builder()
.withSelector(sBuilder.build())
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/OpenstackPipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/OpenstackPipeline.java
index 038b949..91e5b12 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/OpenstackPipeline.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/OpenstackPipeline.java
@@ -17,6 +17,7 @@
import org.onlab.osgi.ServiceDirectory;
import org.onlab.packet.Ethernet;
+import org.onlab.packet.MacAddress;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.DeviceId;
@@ -33,7 +34,11 @@
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.criteria.EthTypeCriterion;
+import org.onosproject.net.flow.criteria.IPCriterion;
+import org.onosproject.net.flow.criteria.PortCriterion;
+import org.onosproject.net.flow.criteria.TunnelIdCriterion;
import org.onosproject.net.flow.criteria.UdpPortCriterion;
+import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flowobjective.FilteringObjective;
import org.onosproject.net.flowobjective.FlowObjectiveStore;
import org.onosproject.net.flowobjective.ForwardingObjective;
@@ -42,9 +47,7 @@
import org.onosproject.net.flowobjective.ObjectiveError;
import org.slf4j.Logger;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Objects;
+import java.util.Optional;
import static org.slf4j.LoggerFactory.getLogger;
@@ -62,14 +65,20 @@
protected ApplicationId appId;
protected FlowRuleService flowRuleService;
- protected static final int VNI_TABLE = 0;
- protected static final int FORWARDING_TABLE = 1;
- protected static final int ACL_TABLE = 2;
+ protected static final int SRC_VNI_TABLE = 0;
+ protected static final int ACL_TABLE = 1;
+ protected static final int CT_TABLE = 2;
+ protected static final int JUMP_TABLE = 3;
+ protected static final int ROUTING_TABLE = 4;
+ protected static final int FORWARDING_TABLE = 5;
+ protected static final int DUMMY_TABLE = 10;
+ protected static final int LAST_TABLE = FORWARDING_TABLE;
private static final int DROP_PRIORITY = 0;
+ private static final int HIGH_PRIORITY = 30000;
private static final int TIME_OUT = 0;
private static final int DHCP_SERVER_PORT = 67;
- private static final int DHCP_CLIENT_PORT = 68;
+ private static final String VIRTUAL_GATEWAY_MAC = "fe:00:00:00:00:02";
@Override
@@ -100,102 +109,110 @@
@Override
public void forward(ForwardingObjective forwardingObjective) {
- Collection<FlowRule> rules;
- FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations.builder();
+ FlowRule flowRule;
- rules = processForward(forwardingObjective);
-
- switch (forwardingObjective.op()) {
- case ADD:
- rules.stream()
- .filter(Objects::nonNull)
- .forEach(flowOpsBuilder::add);
+ switch (forwardingObjective.flag()) {
+ case SPECIFIC:
+ flowRule = processSpecific(forwardingObjective);
break;
- case REMOVE:
- rules.stream()
- .filter(Objects::nonNull)
- .forEach(flowOpsBuilder::remove);
+ case VERSATILE:
+ flowRule = processVersatile(forwardingObjective);
break;
default:
fail(forwardingObjective, ObjectiveError.UNKNOWN);
- log.warn("Unknown forwarding type {}");
+ log.warn("Unknown forwarding flag {}", forwardingObjective.flag());
+ return;
}
- flowRuleService.apply(flowOpsBuilder.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- pass(forwardingObjective);
- }
+ if (forwardingObjective.op().equals(Objective.Operation.ADD)) {
+ applyRules(true, flowRule);
+ } else {
+ applyRules(false, flowRule);
+ }
- @Override
- public void onError(FlowRuleOperations ops) {
- fail(forwardingObjective, ObjectiveError.FLOWINSTALLATIONFAILED);
- }
- }));
}
private void initializePipeline() {
- processVniTable(true);
- processForwardingTable(true);
- processAclTable(true);
+ connectTables(SRC_VNI_TABLE, ACL_TABLE); // Table 0 -> Table 1
+ //FIXME CT table needs to be reconstructed using OVS 2.5 connection tracking feature.
+ connectTables(CT_TABLE, JUMP_TABLE); // Table 2 -> Table 3
+ setUpTableMissEntry(ACL_TABLE);
+ setupJumpTable();
}
- private void processVniTable(boolean install) {
+ private void connectTables(int fromTable, int toTable) {
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ treatment.transition(toTable);
+
+ FlowRule flowRule = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .withSelector(selector.build())
+ .withTreatment(treatment.build())
+ .withPriority(DROP_PRIORITY)
+ .fromApp(appId)
+ .makePermanent()
+ .forTable(fromTable)
+ .build();
+
+ applyRules(true, flowRule);
+ }
+
+ private void setUpTableMissEntry(int table) {
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+
+ treatment.drop();
+
+ FlowRule flowRule = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .withSelector(selector.build())
+ .withTreatment(treatment.build())
+ .withPriority(DROP_PRIORITY)
+ .fromApp(appId)
+ .makePermanent()
+ .forTable(table)
+ .build();
+
+ applyRules(true, flowRule);
+ }
+
+ private void setupJumpTable() {
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+
+ selector.matchEthDst(MacAddress.valueOf(VIRTUAL_GATEWAY_MAC));
+ treatment.transition(ROUTING_TABLE);
+
+ FlowRule flowRule = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .withSelector(selector.build())
+ .withTreatment(treatment.build())
+ .withPriority(HIGH_PRIORITY)
+ .fromApp(appId)
+ .makePermanent()
+ .forTable(JUMP_TABLE)
+ .build();
+
+ applyRules(true, flowRule);
+
+ selector = DefaultTrafficSelector.builder();
+ treatment = DefaultTrafficTreatment.builder();
+
treatment.transition(FORWARDING_TABLE);
- FlowRule flowRule = DefaultFlowRule.builder()
+ flowRule = DefaultFlowRule.builder()
.forDevice(deviceId)
.withSelector(selector.build())
.withTreatment(treatment.build())
.withPriority(DROP_PRIORITY)
.fromApp(appId)
.makePermanent()
- .forTable(VNI_TABLE)
+ .forTable(JUMP_TABLE)
.build();
- applyRules(install, flowRule);
- }
-
- private void processForwardingTable(boolean install) {
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
-
- treatment.drop();
-
- FlowRule flowRule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(DROP_PRIORITY)
- .fromApp(appId)
- .makePermanent()
- .forTable(FORWARDING_TABLE)
- .build();
-
- applyRules(install, flowRule);
- }
-
- private void processAclTable(boolean install) {
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
-
- treatment.wipeDeferred();
- treatment.drop();
-
- FlowRule flowRule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(DROP_PRIORITY)
- .fromApp(appId)
- .makePermanent()
- .forTable(ACL_TABLE)
- .build();
-
- applyRules(install, flowRule);
+ applyRules(true, flowRule);
}
private void applyRules(boolean install, FlowRule flowRule) {
@@ -216,20 +233,7 @@
}));
}
- private Collection<FlowRule> processForward(ForwardingObjective forwardingObjective) {
- switch (forwardingObjective.flag()) {
- case SPECIFIC:
- return processSpecific(forwardingObjective);
- case VERSATILE:
- return processVersatile(forwardingObjective);
- default:
- fail(forwardingObjective, ObjectiveError.UNKNOWN);
- log.warn("Unknown forwarding flag {}", forwardingObjective.flag());
- }
- return Collections.emptySet();
- }
-
- private Collection<FlowRule> processVersatile(ForwardingObjective forwardingObjective) {
+ private FlowRule processVersatile(ForwardingObjective forwardingObjective) {
log.debug("Processing versatile forwarding objective");
FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
@@ -253,25 +257,39 @@
if (ethCriterion != null) {
if (ethCriterion.ethType().toShort() == Ethernet.TYPE_ARP ||
ethCriterion.ethType().toShort() == Ethernet.TYPE_LLDP) {
- ruleBuilder.forTable(VNI_TABLE);
- return Collections.singletonList(ruleBuilder.build());
+ ruleBuilder.forTable(SRC_VNI_TABLE);
+ return ruleBuilder.build();
} else if (udpPortCriterion != null && udpPortCriterion.udpPort().toInt() == DHCP_SERVER_PORT) {
- ruleBuilder.forTable(VNI_TABLE);
- return Collections.singletonList(ruleBuilder.build());
+ ruleBuilder.forTable(SRC_VNI_TABLE);
+ return ruleBuilder.build();
}
}
- return Collections.emptySet();
+
+ return null;
}
- private Collection<FlowRule> processSpecific(ForwardingObjective forwardingObjective) {
+ private FlowRule processSpecific(ForwardingObjective forwardingObjective) {
log.debug("Processing specific forwarding objective");
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+
+
+ Optional<Instruction> group = forwardingObjective.treatment().immediate().stream()
+ .filter(i -> i.type() == Instruction.Type.GROUP).findAny();
+ int tableType = tableType(forwardingObjective);
+ if (tableType != LAST_TABLE && !group.isPresent()) {
+ treatment.transition(nextTable(tableType));
+ }
+ forwardingObjective.treatment().allInstructions().stream()
+ .filter(i -> i.type() != Instruction.Type.NOACTION).forEach(treatment::add);
+
FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
.forDevice(deviceId)
.withSelector(forwardingObjective.selector())
- .withTreatment(forwardingObjective.treatment())
+ .withTreatment(treatment.build())
.withPriority(forwardingObjective.priority())
- .fromApp(forwardingObjective.appId());
+ .fromApp(forwardingObjective.appId())
+ .forTable(tableType);
if (forwardingObjective.permanent()) {
ruleBuilder.makePermanent();
@@ -279,30 +297,41 @@
ruleBuilder.makeTemporary(TIME_OUT);
}
- //VNI Table Rule
- if (forwardingObjective.selector().getCriterion(Criterion.Type.IN_PORT) != null) {
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
- forwardingObjective.treatment().allInstructions().forEach(tBuilder::add);
- tBuilder.transition(FORWARDING_TABLE);
- ruleBuilder.withTreatment(tBuilder.build());
- ruleBuilder.forTable(VNI_TABLE);
- } else if (forwardingObjective.selector().getCriterion(Criterion.Type.TUNNEL_ID) != null) {
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
- tBuilder.deferred();
- forwardingObjective.treatment().allInstructions().forEach(tBuilder::add);
- tBuilder.transition(ACL_TABLE);
- ruleBuilder.withTreatment(tBuilder.build());
- ruleBuilder.forTable(FORWARDING_TABLE);
- } else {
- ruleBuilder.forTable(ACL_TABLE);
- }
-
- return Collections.singletonList(ruleBuilder.build());
+ return ruleBuilder.build();
}
+ int tableType(ForwardingObjective fo) {
- private void pass(Objective obj) {
- obj.context().ifPresent(context -> context.onSuccess(obj));
+ IPCriterion ipSrc = (IPCriterion) fo.selector().getCriterion(Criterion.Type.IPV4_SRC);
+ IPCriterion ipDst = (IPCriterion) fo.selector().getCriterion(Criterion.Type.IPV4_DST);
+ TunnelIdCriterion tunnelId =
+ (TunnelIdCriterion) fo.selector().getCriterion(Criterion.Type.TUNNEL_ID);
+ PortCriterion inPort = (PortCriterion) fo.selector().getCriterion(Criterion.Type.IN_PORT);
+ Optional<Instruction> output = fo.treatment().immediate().stream()
+ .filter(i -> i.type() == Instruction.Type.OUTPUT).findAny();
+ Optional<Instruction> group = fo.treatment().immediate().stream()
+ .filter(i -> i.type() == Instruction.Type.GROUP).findAny();
+
+ // TODO: Add the Connection Tracking Table
+ if (inPort != null) {
+ return SRC_VNI_TABLE;
+ } else if (output.isPresent()) {
+ return FORWARDING_TABLE;
+ } else if ((ipSrc != null && ipSrc.ip().prefixLength() == 32 &&
+ ipDst != null && ipDst.ip().prefixLength() == 32) ||
+ (ipSrc != null && ipSrc.ip().prefixLength() == 32 && ipDst == null) ||
+ (ipDst != null && ipDst.ip().prefixLength() == 32 && ipSrc == null)) {
+ return ACL_TABLE;
+ } else if ((tunnelId != null && ipSrc != null && ipDst != null) || group.isPresent()) {
+ return ROUTING_TABLE;
+ }
+
+ return DUMMY_TABLE;
+ }
+
+ int nextTable(int baseTable) {
+
+ return baseTable + 1;
}
private void fail(Objective obj, ObjectiveError error) {