/** * Sends an APR request for the target IP address to all ports except in-port. * * @param deviceId Switch device ID * @param targetAddress target IP address for ARP * @param inPort in-port */ public void sendArpRequest(DeviceId deviceId, IpAddress targetAddress, ConnectPoint inPort) { byte[] senderMacAddress; byte[] senderIpAddress; try { senderMacAddress = config.getDeviceMac(deviceId).toBytes(); senderIpAddress = config.getRouterIp(deviceId).toOctets(); } catch (DeviceConfigNotFoundException e) { log.warn(e.getMessage() + " Aborting sendArpRequest."); return; } ARP arpRequest = new ARP(); arpRequest .setHardwareType(ARP.HW_TYPE_ETHERNET) .setProtocolType(ARP.PROTO_TYPE_IP) .setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH) .setProtocolAddressLength((byte) Ip4Address.BYTE_LENGTH) .setOpCode(ARP.OP_REQUEST) .setSenderHardwareAddress(senderMacAddress) .setTargetHardwareAddress(MacAddress.ZERO.toBytes()) .setSenderProtocolAddress(senderIpAddress) .setTargetProtocolAddress(targetAddress.toOctets()); Ethernet eth = new Ethernet(); eth.setDestinationMACAddress(MacAddress.BROADCAST.toBytes()) .setSourceMACAddress(senderMacAddress) .setEtherType(Ethernet.TYPE_ARP) .setPayload(arpRequest); removeVlanAndFlood(eth, inPort); }
private boolean isArpForRouter(DeviceId deviceId, ARP arpMsg) { Ip4Address targetProtocolAddress = Ip4Address.valueOf(arpMsg.getTargetProtocolAddress()); Set<Ip4Address> gatewayIpAddresses = null; try { if (targetProtocolAddress.equals(config.getRouterIp(deviceId))) { return true; } gatewayIpAddresses = config.getPortIPs(deviceId); } catch (DeviceConfigNotFoundException e) { log.warn(e.getMessage() + " Aborting check for router IP in processing arp"); } if (gatewayIpAddresses != null && gatewayIpAddresses.contains(targetProtocolAddress)) { return true; } return false; }
/** * Process incoming ICMP packet. If it is an ICMP request to router or known host, then sends an * ICMP response. If it is an ICMP packet to known host and forward the packet to the host. If it * is an ICMP packet to unknown host in a subnet, then sends an ARP request to the subnet. * * @param pkt inbound packet */ public void processPacketIn(InboundPacket pkt) { Ethernet ethernet = pkt.parsed(); IPv4 ipv4 = (IPv4) ethernet.getPayload(); ConnectPoint connectPoint = pkt.receivedFrom(); DeviceId deviceId = connectPoint.deviceId(); Ip4Address destinationAddress = Ip4Address.valueOf(ipv4.getDestinationAddress()); Set<Ip4Address> gatewayIpAddresses = config.getPortIPs(deviceId); Ip4Address routerIp; try { routerIp = config.getRouterIp(deviceId); } catch (DeviceConfigNotFoundException e) { log.warn(e.getMessage() + " Aborting processPacketIn."); return; } IpPrefix routerIpPrefix = IpPrefix.valueOf(routerIp, IpPrefix.MAX_INET_MASK_LENGTH); Ip4Address routerIpAddress = routerIpPrefix.getIp4Prefix().address(); // ICMP to the router IP or gateway IP if (((ICMP) ipv4.getPayload()).getIcmpType() == ICMP.TYPE_ECHO_REQUEST && (destinationAddress.equals(routerIpAddress) || gatewayIpAddresses.contains(destinationAddress))) { sendICMPResponse(ethernet, connectPoint); // ICMP for any known host } else if (!srManager.hostService.getHostsByIp(destinationAddress).isEmpty()) { // TODO: known host packet should not be coming to controller - resend flows? srManager.ipHandler.forwardPackets(deviceId, destinationAddress); // ICMP for an unknown host in the subnet of the router } else if (config.inSameSubnet(deviceId, destinationAddress)) { srManager.arpHandler.sendArpRequest(deviceId, destinationAddress, connectPoint); // ICMP for an unknown host } else { log.debug("ICMP request for unknown host {} ", destinationAddress); // Do nothing } }