From 4fa1f5e1578fbfd2b3b9cae07bcdfbfec2d31950 Mon Sep 17 00:00:00 2001 From: Daniel Park Date: Wed, 17 Oct 2018 12:41:52 +0900 Subject: [PATCH] Send GARP packet in case floating ip is associated and gateway node is updated. Change-Id: I9aa4172bebdc25de5998b3b3123639bce7d865a0 --- .../api/InstancePortService.java | 8 ++ .../impl/InstancePortManager.java | 9 ++ .../impl/OpenstackRoutingArpHandler.java | 81 +++++++++-- .../OpenstackRoutingFloatingIpHandler.java | 81 +++++------ .../util/OpenstackNetworkingUtil.java | 129 ++++++++++++++++++ .../impl/InstancePortServiceAdapter.java | 5 + 6 files changed, 255 insertions(+), 58 deletions(-) diff --git a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/InstancePortService.java b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/InstancePortService.java index d9890db61d..b6c99fb33d 100644 --- a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/InstancePortService.java +++ b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/InstancePortService.java @@ -63,6 +63,14 @@ public interface InstancePortService */ InstancePort instancePort(DeviceId deviceId, PortNumber portNumber); + /** + * Returns instance ports with the given device identifier. + * + * @param deviceId device identifier + * @return set of instance ports; empty list if no port exists + */ + Set instancePort(DeviceId deviceId); + /** * Returns all instance ports. * diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/InstancePortManager.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/InstancePortManager.java index 8d346a9998..2ddb18195e 100644 --- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/InstancePortManager.java +++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/InstancePortManager.java @@ -225,6 +225,15 @@ public class InstancePortManager .findFirst().orElse(null); } + @Override + public Set instancePort(DeviceId deviceId) { + Set ports = instancePortStore.instancePorts().stream() + .filter(port -> port.deviceId().equals(deviceId)) + .collect(Collectors.toSet()); + + return ImmutableSet.copyOf(ports); + } + @Override public Set instancePorts() { Set ports = instancePortStore.instancePorts(); diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingArpHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingArpHandler.java index 084e969eb4..c711dede4b 100644 --- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingArpHandler.java +++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingArpHandler.java @@ -51,6 +51,7 @@ import org.onosproject.net.packet.PacketContext; import org.onosproject.net.packet.PacketProcessor; import org.onosproject.net.packet.PacketService; import org.onosproject.openstacknetworking.api.Constants; +import org.onosproject.openstacknetworking.api.ExternalPeerRouter; import org.onosproject.openstacknetworking.api.InstancePort; import org.onosproject.openstacknetworking.api.InstancePortAdminService; import org.onosproject.openstacknetworking.api.InstancePortEvent; @@ -60,10 +61,11 @@ import org.onosproject.openstacknetworking.api.OpenstackNetworkAdminService; import org.onosproject.openstacknetworking.api.OpenstackNetworkEvent; import org.onosproject.openstacknetworking.api.OpenstackNetworkListener; import org.onosproject.openstacknetworking.api.OpenstackNetworkService; +import org.onosproject.openstacknetworking.api.OpenstackRouterAdminService; import org.onosproject.openstacknetworking.api.OpenstackRouterEvent; import org.onosproject.openstacknetworking.api.OpenstackRouterListener; -import org.onosproject.openstacknetworking.api.OpenstackRouterService; import org.onosproject.openstacknetworking.api.PreCommitPortService; +import org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil; import org.onosproject.openstacknode.api.OpenstackNode; import org.onosproject.openstacknode.api.OpenstackNodeEvent; import org.onosproject.openstacknode.api.OpenstackNodeListener; @@ -71,6 +73,7 @@ import org.onosproject.openstacknode.api.OpenstackNodeService; import org.openstack4j.model.network.ExternalGateway; import org.openstack4j.model.network.IP; import org.openstack4j.model.network.NetFloatingIP; +import org.openstack4j.model.network.Network; import org.openstack4j.model.network.Port; import org.openstack4j.model.network.Router; import org.osgi.service.component.ComponentContext; @@ -98,7 +101,9 @@ import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.g import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getGwByInstancePort; import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getPropertyValue; import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.isAssociatedWithVM; +import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.processGratuitousArpPacketForFloatingIp; import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.swapStaleLocation; +import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.COMPUTE; import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.GATEWAY; import static org.slf4j.LoggerFactory.getLogger; @@ -124,7 +129,7 @@ public class OpenstackRoutingArpHandler { protected OpenstackNetworkAdminService osNetworkAdminService; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected OpenstackRouterService osRouterService; + protected OpenstackRouterAdminService osRouterAdminService; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected OpenstackNodeService osNodeService; @@ -174,7 +179,7 @@ public class OpenstackRoutingArpHandler { appId = coreService.registerApplication(OPENSTACK_NETWORKING_APP_ID); configService.registerProperties(getClass()); localNodeId = clusterService.getLocalNode().id(); - osRouterService.addListener(osRouterListener); + osRouterAdminService.addListener(osRouterListener); osNodeService.addListener(osNodeListener); osNetworkService.addListener(osNetworkListener); instancePortService.addListener(instPortListener); @@ -187,7 +192,7 @@ public class OpenstackRoutingArpHandler { protected void deactivate() { packetService.removeProcessor(packetProcessor); instancePortService.removeListener(instPortListener); - osRouterService.removeListener(osRouterListener); + osRouterAdminService.removeListener(osRouterListener); osNodeService.removeListener(osNodeListener); osNetworkService.removeListener(osNetworkListener); instancePortService.removeListener(instPortListener); @@ -221,7 +226,7 @@ public class OpenstackRoutingArpHandler { MacAddress targetMac = null; - NetFloatingIP floatingIP = osRouterService.floatingIps().stream() + NetFloatingIP floatingIP = osRouterAdminService.floatingIps().stream() .filter(ip -> ip.getFloatingIpAddress().equals(targetIp.toString())) .findAny().orElse(null); @@ -359,14 +364,14 @@ public class OpenstackRoutingArpHandler { if (completedGws.contains(gateway)) { if (completedGws.size() > 1) { finalGws.remove(gateway); - osRouterService.floatingIps().forEach(fip -> { + osRouterAdminService.floatingIps().forEach(fip -> { if (fip.getPortId() != null) { setFloatingIpArpRule(fip, fip.getPortId(), finalGws, false); finalGws.add(gateway); } }); } - osRouterService.floatingIps().forEach(fip -> { + osRouterAdminService.floatingIps().forEach(fip -> { if (fip.getPortId() != null) { setFloatingIpArpRule(fip, fip.getPortId(), finalGws, true); } @@ -377,14 +382,14 @@ public class OpenstackRoutingArpHandler { } else { if (!completedGws.contains(gateway)) { finalGws.add(gateway); - osRouterService.floatingIps().forEach(fip -> { + osRouterAdminService.floatingIps().forEach(fip -> { if (fip.getPortId() != null) { setFloatingIpArpRule(fip, fip.getPortId(), finalGws, false); } }); finalGws.remove(gateway); if (completedGws.size() >= 1) { - osRouterService.floatingIps().forEach(fip -> { + osRouterAdminService.floatingIps().forEach(fip -> { if (fip.getPortId() != null) { setFloatingIpArpRule(fip, fip.getPortId(), finalGws, true); } @@ -730,14 +735,14 @@ public class OpenstackRoutingArpHandler { public void event(InstancePortEvent event) { InstancePort instPort = event.subject(); - Set ips = osRouterService.floatingIps(); + Set ips = osRouterAdminService.floatingIps(); NetFloatingIP fip = associatedFloatingIp(instPort, ips); Set gateways = osNodeService.completeNodes(GATEWAY); switch (event.type()) { case OPENSTACK_INSTANCE_PORT_DETECTED: - osRouterService.floatingIps().stream() + osRouterAdminService.floatingIps().stream() .filter(f -> f.getPortId() != null) .filter(f -> f.getPortId().equals(instPort.portId())) .forEach(f -> setFloatingIpArpRule(f, instPort.portId(), gateways, true)); @@ -803,16 +808,68 @@ public class OpenstackRoutingArpHandler { case OPENSTACK_NODE_COMPLETE: setDefaultArpRule(osNode, true); setFloatingIpArpRuleForGateway(osNode, true); + sendGratuitousArpToSwitch(event.subject(), true); break; case OPENSTACK_NODE_INCOMPLETE: setDefaultArpRule(osNode, false); setFloatingIpArpRuleForGateway(osNode, false); + sendGratuitousArpToSwitch(event.subject(), false); break; + case OPENSTACK_NODE_REMOVED: + sendGratuitousArpToSwitch(event.subject(), false); + break; + default: break; } } + private void sendGratuitousArpToSwitch(OpenstackNode gatewayNode, boolean isCompleteCase) { + Set completeGws = ImmutableSet.copyOf(osNodeService.completeNodes(GATEWAY)); + + if (isCompleteCase) { + osNodeService.completeNodes(COMPUTE) + .stream() + .filter(node -> isGwSelectedByComputeNode(completeGws, node, gatewayNode)) + .forEach(node -> processGratuitousArpPacketForComputeNode(node, gatewayNode)); + + } else { + Set oldCompleteGws = Sets.newConcurrentHashSet(); + oldCompleteGws.addAll(ImmutableSet.copyOf(osNodeService.completeNodes(GATEWAY))); + oldCompleteGws.add(gatewayNode); + + osNodeService.completeNodes(COMPUTE) + .stream() + .filter(node -> isGwSelectedByComputeNode(oldCompleteGws, node, gatewayNode)) + .forEach(node -> { + OpenstackNode newSelectedGatewayNode = getGwByComputeDevId(completeGws, node.intgBridge()); + processGratuitousArpPacketForComputeNode(node, newSelectedGatewayNode); + }); + } + } + + private boolean isGwSelectedByComputeNode(Set gws, + OpenstackNode computeNode, + OpenstackNode gwNode) { + return OpenstackNetworkingUtil + .getGwByComputeDevId(gws, computeNode.intgBridge()) + .intgBridge().equals(gwNode.intgBridge()); + } + + private void processGratuitousArpPacketForComputeNode(OpenstackNode computeNode, OpenstackNode gatewayNode) { + instancePortService.instancePort(computeNode.intgBridge()).forEach(instancePort -> { + NetFloatingIP floatingIP = OpenstackNetworkingUtil.floatingIpByInstancePort(instancePort, + osRouterAdminService); + Network network = osNetworkService.network(instancePort.networkId()); + ExternalPeerRouter externalPeerRouter = OpenstackNetworkingUtil.externalPeerRouterForNetwork(network, + osNetworkService, osRouterAdminService); + if (floatingIP != null && externalPeerRouter != null) { + processGratuitousArpPacketForFloatingIp( + floatingIP, instancePort, externalPeerRouter.vlanId(), gatewayNode, packetService); + } + }); + } + private void setDefaultArpRule(OpenstackNode osNode, boolean install) { switch (getArpMode()) { case ARP_PROXY_MODE: @@ -871,7 +928,7 @@ public class OpenstackRoutingArpHandler { install ); - osRouterService.routers().stream() + osRouterAdminService.routers().stream() .filter(router -> router.getExternalGatewayInfo() != null) .forEach(router -> setFakeGatewayArpRuleByRouter(router, install)); } diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java index 60b924b347..731a1151cf 100644 --- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java +++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java @@ -38,6 +38,7 @@ import org.onosproject.net.flow.DefaultTrafficSelector; import org.onosproject.net.flow.DefaultTrafficTreatment; import org.onosproject.net.flow.TrafficSelector; import org.onosproject.net.flow.TrafficTreatment; +import org.onosproject.net.packet.PacketService; import org.onosproject.openstacknetworking.api.Constants; import org.onosproject.openstacknetworking.api.ExternalPeerRouter; import org.onosproject.openstacknetworking.api.InstancePort; @@ -56,14 +57,10 @@ import org.onosproject.openstacknode.api.OpenstackNode; import org.onosproject.openstacknode.api.OpenstackNodeEvent; import org.onosproject.openstacknode.api.OpenstackNodeListener; import org.onosproject.openstacknode.api.OpenstackNodeService; -import org.openstack4j.model.network.ExternalGateway; import org.openstack4j.model.network.NetFloatingIP; import org.openstack4j.model.network.Network; import org.openstack4j.model.network.NetworkType; import org.openstack4j.model.network.Port; -import org.openstack4j.model.network.Router; -import org.openstack4j.model.network.RouterInterface; -import org.openstack4j.model.network.Subnet; import org.openstack4j.openstack.networking.domain.NeutronFloatingIP; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -84,8 +81,11 @@ import static org.onosproject.openstacknetworking.api.InstancePortEvent.Type.OPE import static org.onosproject.openstacknetworking.api.InstancePortEvent.Type.OPENSTACK_INSTANCE_MIGRATION_STARTED; import static org.onosproject.openstacknetworking.api.OpenstackNetworkEvent.Type.OPENSTACK_PORT_PRE_REMOVE; import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.associatedFloatingIp; +import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.externalPeerRouterForNetwork; import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getGwByComputeDevId; +import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getGwByInstancePort; import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.isAssociatedWithVM; +import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.processGratuitousArpPacketForFloatingIp; import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.swapStaleLocation; import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.buildExtension; import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.GATEWAY; @@ -131,6 +131,9 @@ public class OpenstackRoutingFloatingIpHandler { @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected PreCommitPortService preCommitPortService; + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected PacketService packetService; + private final ExecutorService eventExecutor = newSingleThreadExecutor( groupedThreads(this.getClass().getSimpleName(), "event-handler", log)); private final OpenstackRouterListener floatingIpListener = new InternalFloatingIpListener(); @@ -180,15 +183,8 @@ public class OpenstackRoutingFloatingIpHandler { Network osNet = osNetworkService.network(instPort.networkId()); - if (osNet == null) { - final String errorFormat = ERR_FLOW + "no network(%s) exists"; - final String error = String.format(errorFormat, - floatingIp.getFloatingIpAddress(), - instPort.networkId()); - throw new IllegalStateException(error); - } - - ExternalPeerRouter externalPeerRouter = externalPeerRouter(osNet); + ExternalPeerRouter externalPeerRouter = externalPeerRouterForNetwork(osNet, + osNetworkService, osRouterAdminService); if (externalPeerRouter == null) { final String errorFormat = ERR_FLOW + "no external peer router found"; throw new IllegalStateException(errorFormat); @@ -491,36 +487,6 @@ public class OpenstackRoutingFloatingIpHandler { log.trace("Succeeded to set flow rules for upstream on gateway nodes"); } - private ExternalPeerRouter externalPeerRouter(Network network) { - if (network == null) { - return null; - } - - Subnet subnet = osNetworkService.subnets(network.getId()).stream().findAny().orElse(null); - - if (subnet == null) { - return null; - } - - RouterInterface osRouterIface = osRouterAdminService.routerInterfaces().stream() - .filter(i -> Objects.equals(i.getSubnetId(), subnet.getId())) - .findAny().orElse(null); - if (osRouterIface == null) { - return null; - } - - Router osRouter = osRouterAdminService.router(osRouterIface.getId()); - if (osRouter == null) { - return null; - } - if (osRouter.getExternalGatewayInfo() == null) { - return null; - } - - ExternalGateway exGatewayInfo = osRouter.getExternalGatewayInfo(); - return osNetworkService.externalPeerRouter(exGatewayInfo); - } - private void associateFloatingIp(NetFloatingIP osFip) { InstancePort instPort = instancePortService.instancePort(osFip.getPortId()); @@ -533,9 +499,31 @@ public class OpenstackRoutingFloatingIpHandler { // set floating IP rules only if the port is associated to a VM if (!Strings.isNullOrEmpty(instPort.deviceId().toString())) { setFloatingIpRules(osFip, instPort, null, true); + processGratuitousArpPacket(osFip, instPort); + } } + private void processGratuitousArpPacket(NetFloatingIP floatingIP, + InstancePort instancePort) { + Set gws = ImmutableSet.copyOf(osNodeService.completeNodes(GATEWAY)); + + Network osNet = osNetworkService.network(instancePort.networkId()); + + + OpenstackNode selectedGw = getGwByInstancePort(gws, instancePort); + ExternalPeerRouter externalPeerRouter = + externalPeerRouterForNetwork(osNet, osNetworkService, osRouterAdminService); + if (externalPeerRouter == null) { + log.error("Failed to process GARP packet for floating ip {} because no external peer router found"); + return; + } + + processGratuitousArpPacketForFloatingIp(floatingIP, instancePort, externalPeerRouter.vlanId(), + selectedGw, packetService); + + } + private void disassociateFloatingIp(NetFloatingIP osFip, String portId) { InstancePort instPort = instancePortService.instancePort(portId); @@ -701,7 +689,8 @@ public class OpenstackRoutingFloatingIpHandler { throw new IllegalStateException(error); } - ExternalPeerRouter externalPeerRouter = externalPeerRouter(osNet); + ExternalPeerRouter externalPeerRouter = externalPeerRouterForNetwork(osNet, + osNetworkService, osRouterAdminService); if (externalPeerRouter == null) { final String errorFormat = ERR_FLOW + "no external peer router found"; throw new IllegalStateException(errorFormat); @@ -776,7 +765,7 @@ public class OpenstackRoutingFloatingIpHandler { osPort = osNetworkService.port(fip.getPortId()); osNet = osNetworkService.network(osPort.getNetworkId()); - externalPeerRouter = externalPeerRouter(osNet); + externalPeerRouter = externalPeerRouterForNetwork(osNet, osNetworkService, osRouterAdminService); if (externalPeerRouter == null) { final String errorFormat = ERR_FLOW + "no external peer router found"; @@ -809,7 +798,7 @@ public class OpenstackRoutingFloatingIpHandler { osPort = osNetworkService.port(fip.getPortId()); osNet = osNetworkService.network(osPort.getNetworkId()); - externalPeerRouter = externalPeerRouter(osNet); + externalPeerRouter = externalPeerRouterForNetwork(osNet, osNetworkService, osRouterAdminService); if (externalPeerRouter == null) { final String errorFormat = ERR_FLOW + "no external peer router found"; diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java index b7550176a6..db15e154fe 100644 --- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java +++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java @@ -42,11 +42,21 @@ import org.apache.sshd.client.channel.ClientChannelEvent; import org.apache.sshd.client.future.OpenFuture; import org.apache.sshd.client.session.ClientSession; import org.apache.sshd.common.util.io.NoCloseInputStream; +import org.onlab.packet.ARP; +import org.onlab.packet.Ethernet; +import org.onlab.packet.Ip4Address; import org.onlab.packet.IpAddress; +import org.onlab.packet.MacAddress; +import org.onlab.packet.VlanId; import org.onosproject.cfg.ConfigProperty; import org.onosproject.net.DeviceId; import org.onosproject.net.device.DeviceService; +import org.onosproject.net.flow.DefaultTrafficTreatment; +import org.onosproject.net.flow.TrafficTreatment; +import org.onosproject.net.packet.DefaultOutboundPacket; +import org.onosproject.net.packet.PacketService; import org.onosproject.openstacknetworking.api.Constants.VnicType; +import org.onosproject.openstacknetworking.api.ExternalPeerRouter; import org.onosproject.openstacknetworking.api.InstancePort; import org.onosproject.openstacknetworking.api.OpenstackNetworkService; import org.onosproject.openstacknetworking.api.OpenstackRouterAdminService; @@ -63,10 +73,13 @@ import org.openstack4j.core.transport.Config; import org.openstack4j.core.transport.ObjectMapperSingleton; import org.openstack4j.model.ModelEntity; import org.openstack4j.model.common.Identifier; +import org.openstack4j.model.network.ExternalGateway; import org.openstack4j.model.network.NetFloatingIP; import org.openstack4j.model.network.Network; import org.openstack4j.model.network.Port; +import org.openstack4j.model.network.Router; import org.openstack4j.model.network.RouterInterface; +import org.openstack4j.model.network.Subnet; import org.openstack4j.openstack.OSFactory; import org.openstack4j.openstack.networking.domain.NeutronRouterInterface; import org.slf4j.Logger; @@ -84,6 +97,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.nio.ByteBuffer; import java.security.cert.X509Certificate; import java.util.Collection; import java.util.HashMap; @@ -846,10 +860,125 @@ public final class OpenstackNetworkingUtil { return traceResult; } + /** + * Returns the floating ip with supplied instance port. + * + * @param instancePort instance port + * @param osRouterAdminService openstack router admin service + * @return floating ip + */ + public static NetFloatingIP floatingIpByInstancePort(InstancePort instancePort, + OpenstackRouterAdminService osRouterAdminService) { + return osRouterAdminService.floatingIps().stream() + .filter(netFloatingIP -> netFloatingIP.getPortId() != null) + .filter(netFloatingIP -> netFloatingIP.getPortId().equals(instancePort.portId())) + .findAny().orElse(null); + } + + /** + * Sends GARP packet with supplied floating ip information. + * + * @param floatingIP floating ip + * @param instancePort instance port + * @param vlanId vlain id + * @param gatewayNode gateway node + * @param packetService packet service + */ + public static void processGratuitousArpPacketForFloatingIp(NetFloatingIP floatingIP, + InstancePort instancePort, + VlanId vlanId, + OpenstackNode gatewayNode, + PacketService packetService) { + Ethernet ethernet = buildGratuitousArpPacket(floatingIP, instancePort, vlanId); + + TrafficTreatment treatment = DefaultTrafficTreatment.builder() + .setOutput(gatewayNode.uplinkPortNum()).build(); + + packetService.emit(new DefaultOutboundPacket(gatewayNode.intgBridge(), treatment, + ByteBuffer.wrap(ethernet.serialize()))); + } + + /** + * Returns the external peer router with supplied network information. + * + * @param network network + * @param osNetworkService openstack network service + * @param osRouterAdminService openstack router admin service + * @return external peer router + */ + public static ExternalPeerRouter externalPeerRouterForNetwork(Network network, + OpenstackNetworkService osNetworkService, + OpenstackRouterAdminService osRouterAdminService) { + if (network == null) { + return null; + } + + Subnet subnet = osNetworkService.subnets(network.getId()).stream().findAny().orElse(null); + + if (subnet == null) { + return null; + } + + RouterInterface osRouterIface = osRouterAdminService.routerInterfaces().stream() + .filter(i -> Objects.equals(i.getSubnetId(), subnet.getId())) + .findAny().orElse(null); + if (osRouterIface == null) { + return null; + } + + Router osRouter = osRouterAdminService.router(osRouterIface.getId()); + if (osRouter == null) { + return null; + } + if (osRouter.getExternalGatewayInfo() == null) { + return null; + } + + ExternalGateway exGatewayInfo = osRouter.getExternalGatewayInfo(); + return osNetworkService.externalPeerRouter(exGatewayInfo); + + } + private static boolean isDirectPort(String portName) { return portNamePrefixMap().values().stream().anyMatch(p -> portName.startsWith(p)); } + /** + * Returns GARP packet with supplied floating ip and instance port information. + * + * @param floatingIP floating ip + * @param instancePort instance port + * @param vlanId vlan id + * @return GARP packet + */ + private static Ethernet buildGratuitousArpPacket(NetFloatingIP floatingIP, + InstancePort instancePort, + VlanId vlanId) { + Ethernet ethernet = new Ethernet(); + ethernet.setDestinationMACAddress(MacAddress.BROADCAST); + ethernet.setSourceMACAddress(instancePort.macAddress()); + ethernet.setEtherType(Ethernet.TYPE_ARP); + ethernet.setVlanID(vlanId.id()); + + ARP arp = new ARP(); + arp.setOpCode(ARP.OP_REPLY); + arp.setProtocolType(ARP.PROTO_TYPE_IP); + arp.setHardwareType(ARP.HW_TYPE_ETHERNET); + + arp.setProtocolAddressLength((byte) Ip4Address.BYTE_LENGTH); + arp.setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH); + + arp.setSenderHardwareAddress(instancePort.macAddress().toBytes()); + arp.setTargetHardwareAddress(MacAddress.BROADCAST.toBytes()); + + arp.setSenderProtocolAddress(Ip4Address.valueOf(floatingIP.getFloatingIpAddress()).toInt()); + arp.setTargetProtocolAddress(Ip4Address.valueOf(floatingIP.getFloatingIpAddress()).toInt()); + + ethernet.setPayload(arp); + + return ethernet; + } + /** * Builds up and a complete endpoint URL from gateway node. * diff --git a/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/InstancePortServiceAdapter.java b/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/InstancePortServiceAdapter.java index d4f1d3fa08..7d9b75a55b 100644 --- a/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/InstancePortServiceAdapter.java +++ b/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/InstancePortServiceAdapter.java @@ -50,6 +50,11 @@ public class InstancePortServiceAdapter implements InstancePortService { return null; } + @Override + public Set instancePort(DeviceId deviceId) { + return ImmutableSet.of(); + } + @Override public Set instancePorts() { return ImmutableSet.of();