hyungseo Ryu
Committed by Gerrit Code Review

[ONOS-4702] Fixed Openstack ARP/ICMP in OpenstackNetworkingService.

-Fixes ICMP/ARP handler to deals with floatingIP.
-Fixed some bugs in ARP/ICMP handler.

Change-Id: Ie06fdcce25f8a58e2f14e9050bfb7e430ddfd3af
......@@ -347,7 +347,7 @@ public final class OpenstackSecurityGroupRule {
public OpenstackSecurityGroupRule build() {
int portRangeMinInt = (portRangeMin == null || portRangeMin.equals("null")) ?
-1 : Integer.parseInt(portRangeMax);
-1 : Integer.parseInt(portRangeMin);
int portRangeMaxInt = (portRangeMax == null || portRangeMax.equals("null")) ?
-1 : Integer.parseInt(portRangeMax);
IpPrefix ipPrefix = (remoteIpPrefix == null || remoteIpPrefix.equals("null")) ?
......
......@@ -66,14 +66,16 @@ public class OpenstackIcmpHandler {
private static final MacAddress GATEWAY_MAC = MacAddress.valueOf("1f:1f:1f:1f:1f:1f");
private static final String NETWORK_ROUTER_INTERFACE = "network:router_interface";
private static final String PORTNAME = "portName";
private static final String NETWORK_ROUTER_GATEWAY = "network:router_gateway";
private static final String NETWORK_FLOATING_IP = "network:floatingip";
/**
* Default constructor.
*
* @param packetService packet service
* @param deviceService device service
* @param openstackService openstackInterface service
* @param config openstackRoutingConfig
* @param packetService packet service
* @param deviceService device service
* @param openstackService openstackInterface service
* @param config openstackRoutingConfig
* @param openstackSwitchingService openstackSwitching service
*/
OpenstackIcmpHandler(PacketService packetService, DeviceService deviceService,
......@@ -106,7 +108,7 @@ public class OpenstackIcmpHandler {
/**
* Handles ICMP packet.
*
* @param context packet context
* @param context packet context
* @param ethernet ethernet
*/
public void processIcmpPacket(PacketContext context, Ethernet ethernet) {
......@@ -122,13 +124,30 @@ public class OpenstackIcmpHandler {
short icmpId = getIcmpId(icmp);
DeviceId deviceId = context.inPacket().receivedFrom().deviceId();
PortNumber portNumber = context.inPacket().receivedFrom().port();
if (icmp.getIcmpType() == ICMP.TYPE_ECHO_REQUEST) {
//TODO: Considers icmp between internal subnets which are belonged to the same router.
OpenstackPortInfo openstackPortInfo =
getOpenstackPortInfo(Ip4Address.valueOf(ipPacket.getSourceAddress()), ethernet.getSourceMAC());
checkNotNull(openstackPortInfo, "openstackPortInfo can not be null");
//checkNotNull(openstackPortInfo, "openstackPortInfo can not be null");
if (requestToOpenstackRoutingNetwork(ipPacket.getDestinationAddress())) {
if (openstackPortInfo == null) {
if (config.gatewayBridgeId().equals(context.inPacket().receivedFrom().deviceId().toString())) {
if (portNumber.equals(getPortForAnnotationPortName(deviceId,
config.gatewayExternalInterfaceName()))) {
processIcmpPacketSentToExtenal(ipPacket, icmp, ipPacket.getSourceAddress(),
ethernet.getSourceMAC(), deviceId, portNumber);
return;
}
}
return;
} else {
processIcmpPacketSentToGateway(ipPacket, icmp, openstackPortInfo);
return;
}
}
if (ipPacket.getDestinationAddress() == openstackPortInfo.gatewayIP().toInt()) {
processIcmpPacketSentToGateway(ipPacket, icmp, openstackPortInfo);
......@@ -154,8 +173,27 @@ public class OpenstackIcmpHandler {
}
}
private void processIcmpPacketSentToExtenal(IPv4 icmpRequestIpv4, ICMP icmpRequest,
int destAddr, MacAddress destMac,
DeviceId deviceId, PortNumber portNumber) {
icmpRequest.setChecksum((short) 0);
icmpRequest.setIcmpType(ICMP.TYPE_ECHO_REPLY).resetChecksum();
icmpRequestIpv4.setSourceAddress(icmpRequestIpv4.getDestinationAddress())
.setDestinationAddress(destAddr).resetChecksum();
icmpRequestIpv4.setPayload(icmpRequest);
Ethernet icmpResponseEth = new Ethernet();
icmpResponseEth.setEtherType(Ethernet.TYPE_IPV4)
.setSourceMACAddress(config.gatewayExternalInterfaceMac())
.setDestinationMACAddress(destMac).setPayload(icmpRequestIpv4);
TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(portNumber).build();
OutboundPacket packet = new DefaultOutboundPacket(deviceId,
treatment, ByteBuffer.wrap(icmpResponseEth.serialize()));
packetService.emit(packet);
}
private void processIcmpPacketSentToGateway(IPv4 icmpRequestIpv4, ICMP icmpRequest,
OpenstackPortInfo openstackPortInfo) {
icmpRequest.setChecksum((short) 0);
icmpRequest.setIcmpType(ICMP.TYPE_ECHO_REPLY)
.resetChecksum();
......@@ -272,4 +310,17 @@ public class OpenstackIcmpHandler {
return port.number();
}
}
private boolean requestToOpenstackRoutingNetwork(int destAddr) {
OpenstackPort port = openstackService.ports().stream()
.filter(p -> p.deviceOwner().equals(NETWORK_ROUTER_GATEWAY) ||
p.deviceOwner().equals(NETWORK_FLOATING_IP))
.filter(p -> p.fixedIps().containsValue(
Ip4Address.valueOf(destAddr)))
.findAny().orElse(null);
if (port == null) {
return false;
}
return true;
}
}
\ No newline at end of file
......
......@@ -52,6 +52,7 @@ public class OpenstackRoutingArpHandler {
private final OpenstackInterfaceService openstackService;
private final OpenstackNetworkingConfig config;
private static final String NETWORK_ROUTER_GATEWAY = "network:router_gateway";
private static final String NETWORK_FLOATING_IP = "network:floatingip";
/**
* Default constructor.
......@@ -106,11 +107,11 @@ public class OpenstackRoutingArpHandler {
}
IpAddress targetIp = Ip4Address.valueOf(arp.getTargetProtocolAddress());
MacAddress targetMac = getTargetMacForTargetIp(targetIp.getIp4Address());
if (targetMac == MacAddress.NONE) {
return;
if (getTargetMacForTargetIp(targetIp.getIp4Address()) == MacAddress.NONE) {
return;
}
MacAddress targetMac = MacAddress.valueOf(config.gatewayExternalInterfaceMac());
Ethernet ethReply = ARP.buildArpReply(targetIp.getIp4Address(),
targetMac, ethernet);
......@@ -127,7 +128,8 @@ public class OpenstackRoutingArpHandler {
private MacAddress getTargetMacForTargetIp(Ip4Address targetIp) {
OpenstackPort port = openstackService.ports().stream()
.filter(p -> p.deviceOwner().equals(NETWORK_ROUTER_GATEWAY))
.filter(p -> p.deviceOwner().equals(NETWORK_ROUTER_GATEWAY) ||
p.deviceOwner().equals(NETWORK_FLOATING_IP))
.filter(p -> p.fixedIps().containsValue(targetIp.getIp4Address()))
.findAny().orElse(null);
......
......@@ -451,7 +451,7 @@ public class OpenstackRoutingRulePopulator {
sBuilder.matchEthType(Ethernet.TYPE_IPV4)
.matchIPDst(IpPrefix.valueOf(floatingIP.floatingIpAddress(), PREFIX_LENGTH));
tBuilder.setEthSrc(MacAddress.valueOf(config.gatewayExternalInterfaceMac()))
tBuilder.setEthSrc(GATEWAYMAC)
.setEthDst(port.macAddress())
.setIpDst(floatingIP.fixedIpAddress())
.setTunnelId(getVni(port.networkId()))
......
......@@ -126,6 +126,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
public static final Ip4Address DNS_SERVER_IP = Ip4Address.valueOf("8.8.8.8");
private static final String FORWARD_SLASH = "/";
private static final int DHCP_INFINITE_LEASE = -1;
public static final String SONA_DRIVER_NAME = "sona";
private ApplicationId appId;
......@@ -418,8 +419,12 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
@Override
public void process(PacketContext context) {
// FIXME: use GatewayNode list to check if the ARP packet is from GatewayNode's
if (context.isHandled()) {
return;
} else if (!SONA_DRIVER_NAME.equals(driverService
.getDriver(context.inPacket().receivedFrom().deviceId()).name())) {
return;
}
InboundPacket pkt = context.inPacket();
......