Example #1
0
  private void sendPacketOut(ConnectPoint outport, Ethernet payload, int sid) {

    IPv4 ipPacket = (IPv4) payload.getPayload();
    Ip4Address destIpAddress = Ip4Address.valueOf(ipPacket.getDestinationAddress());

    if (sid == -1
        || config.getSegmentId(payload.getDestinationMAC()) == sid
        || config.inSameSubnet(outport.deviceId(), destIpAddress)) {
      TrafficTreatment treatment =
          DefaultTrafficTreatment.builder().setOutput(outport.port()).build();
      OutboundPacket packet =
          new DefaultOutboundPacket(
              outport.deviceId(), treatment, ByteBuffer.wrap(payload.serialize()));
      srManager.packetService.emit(packet);
    } else {
      log.info("Send a MPLS packet as a ICMP response");
      TrafficTreatment treatment =
          DefaultTrafficTreatment.builder().setOutput(outport.port()).build();

      payload.setEtherType(Ethernet.MPLS_UNICAST);
      MPLS mplsPkt = new MPLS();
      mplsPkt.setLabel(sid);
      mplsPkt.setTtl(((IPv4) payload.getPayload()).getTtl());
      mplsPkt.setPayload(payload.getPayload());
      payload.setPayload(mplsPkt);

      OutboundPacket packet =
          new DefaultOutboundPacket(
              outport.deviceId(), treatment, ByteBuffer.wrap(payload.serialize()));

      srManager.packetService.emit(packet);
    }
  }
Example #2
0
  /**
   * 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);
  }
Example #3
0
 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;
 }
Example #4
0
  /**
   * 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
    }
  }
Example #5
0
  /**
   * Sends an ICMP reply message.
   *
   * <p>Note: we assume that packets sending from the edge switches to the hosts have untagged VLAN.
   *
   * @param icmpRequest the original ICMP request
   * @param outport the output port where the ICMP reply should be sent to
   */
  private void sendICMPResponse(Ethernet icmpRequest, ConnectPoint outport) {
    // Note: We assume that packets arrive at the edge switches have
    // untagged VLAN.
    Ethernet icmpReplyEth = new Ethernet();

    IPv4 icmpRequestIpv4 = (IPv4) icmpRequest.getPayload();
    IPv4 icmpReplyIpv4 = new IPv4();

    int destAddress = icmpRequestIpv4.getDestinationAddress();
    icmpReplyIpv4.setDestinationAddress(icmpRequestIpv4.getSourceAddress());
    icmpReplyIpv4.setSourceAddress(destAddress);
    icmpReplyIpv4.setTtl((byte) 64);
    icmpReplyIpv4.setChecksum((short) 0);

    ICMP icmpReply = new ICMP();
    icmpReply.setPayload(((ICMP) icmpRequestIpv4.getPayload()).getPayload());
    icmpReply.setIcmpType(ICMP.TYPE_ECHO_REPLY);
    icmpReply.setIcmpCode(ICMP.SUBTYPE_ECHO_REPLY);
    icmpReply.setChecksum((short) 0);
    icmpReplyIpv4.setPayload(icmpReply);

    icmpReplyEth.setPayload(icmpReplyIpv4);
    icmpReplyEth.setEtherType(Ethernet.TYPE_IPV4);
    icmpReplyEth.setDestinationMACAddress(icmpRequest.getSourceMACAddress());
    icmpReplyEth.setSourceMACAddress(icmpRequest.getDestinationMACAddress());

    Ip4Address destIpAddress = Ip4Address.valueOf(icmpReplyIpv4.getDestinationAddress());
    Ip4Address destRouterAddress = config.getRouterIpAddressForASubnetHost(destIpAddress);
    int sid = config.getSegmentId(destRouterAddress);
    if (sid < 0) {
      log.warn("Cannot find the Segment ID for {}", destAddress);
      return;
    }

    sendPacketOut(outport, icmpReplyEth, sid);
  }
Example #6
0
  private void handleArpRequest(DeviceId deviceId, ConnectPoint inPort, Ethernet payload) {
    ARP arpRequest = (ARP) payload.getPayload();
    VlanId vlanId = VlanId.vlanId(payload.getVlanID());
    HostId targetHostId =
        HostId.hostId(MacAddress.valueOf(arpRequest.getTargetHardwareAddress()), vlanId);

    // ARP request for router. Send ARP reply.
    if (isArpForRouter(deviceId, arpRequest)) {
      Ip4Address targetAddress = Ip4Address.valueOf(arpRequest.getTargetProtocolAddress());
      sendArpResponse(arpRequest, config.getRouterMacForAGatewayIp(targetAddress), vlanId);
    } else {
      Host targetHost = srManager.hostService.getHost(targetHostId);
      // ARP request for known hosts. Send proxy ARP reply on behalf of the target.
      if (targetHost != null) {
        removeVlanAndForward(payload, targetHost.location());
        // ARP request for unknown host in the subnet. Flood in the subnet.
      } else {
        removeVlanAndFlood(payload, inPort);
      }
    }
  }