Example #1
0
  private void sendArpResponse(ARP arpRequest, MacAddress targetMac, VlanId vlanId) {
    ARP arpReply = new ARP();
    arpReply
        .setHardwareType(ARP.HW_TYPE_ETHERNET)
        .setProtocolType(ARP.PROTO_TYPE_IP)
        .setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH)
        .setProtocolAddressLength((byte) Ip4Address.BYTE_LENGTH)
        .setOpCode(ARP.OP_REPLY)
        .setSenderHardwareAddress(targetMac.toBytes())
        .setSenderProtocolAddress(arpRequest.getTargetProtocolAddress())
        .setTargetHardwareAddress(arpRequest.getSenderHardwareAddress())
        .setTargetProtocolAddress(arpRequest.getSenderProtocolAddress());

    Ethernet eth = new Ethernet();
    eth.setDestinationMACAddress(arpRequest.getSenderHardwareAddress())
        .setSourceMACAddress(targetMac.toBytes())
        .setEtherType(Ethernet.TYPE_ARP)
        .setPayload(arpReply);

    MacAddress hostMac = MacAddress.valueOf(arpReply.getTargetHardwareAddress());
    HostId dstId = HostId.hostId(hostMac, vlanId);
    Host dst = srManager.hostService.getHost(dstId);
    if (dst == null) {
      log.warn("Cannot send ARP response to host {}", dstId);
      return;
    }

    TrafficTreatment treatment =
        DefaultTrafficTreatment.builder().setOutput(dst.location().port()).build();
    OutboundPacket packet =
        new DefaultOutboundPacket(
            dst.location().deviceId(), treatment, ByteBuffer.wrap(eth.serialize()));

    srManager.packetService.emit(packet);
  }
Example #2
0
  /**
   * Processes incoming ARP packets.
   *
   * <p>If it is an ARP request to router itself or known hosts, then it sends ARP response. If it
   * is an ARP request to unknown hosts in its own subnet, then it flood the ARP request to the
   * ports. If it is an ARP response, then set a flow rule for the host and forward any IP packets
   * to the host in the packet buffer to the host.
   *
   * <p>Note: We handles all ARP packet in, even for those ARP packets between hosts in the same
   * subnet. For an ARP packet with broadcast destination MAC, some switches pipelines will send it
   * to the controller due to table miss, other swithches will flood the packets directly in the
   * data plane without packet in. We can deal with both cases.
   *
   * @param pkt incoming packet
   */
  public void processPacketIn(InboundPacket pkt) {

    Ethernet ethernet = pkt.parsed();
    ARP arp = (ARP) ethernet.getPayload();

    ConnectPoint connectPoint = pkt.receivedFrom();
    PortNumber inPort = connectPoint.port();
    DeviceId deviceId = connectPoint.deviceId();
    byte[] senderMacAddressByte = arp.getSenderHardwareAddress();
    Ip4Address hostIpAddress = Ip4Address.valueOf(arp.getSenderProtocolAddress());

    srManager.routingRulePopulator.populateIpRuleForHost(
        deviceId, hostIpAddress, MacAddress.valueOf(senderMacAddressByte), inPort);

    if (arp.getOpCode() == ARP.OP_REQUEST) {
      handleArpRequest(deviceId, connectPoint, ethernet);
    } else {
      handleArpReply(deviceId, connectPoint, ethernet);
    }
  }