Пример #1
0
  /**
   * Sends an ARP or Neighbor Discovery Protocol request for the given IP address.
   *
   * @param targetIp IP address to send the request for
   */
  private void sendArpNdpRequest(IpAddress targetIp) {
    Interface intf = interfaceService.getMatchingInterface(targetIp);

    if (intf == null) {
      return;
    }

    for (InterfaceIpAddress ia : intf.ipAddresses()) {
      if (ia.subnetAddress().contains(targetIp)) {
        sendArpNdpProbe(intf.connectPoint(), targetIp, ia.ipAddress(), intf.mac(), intf.vlan());
      }
    }
  }
Пример #2
0
  private void transformAndSend(IPv4 ipv4, Interface egressInterface, MacAddress macAddress) {

    Ethernet eth = new Ethernet();
    eth.setDestinationMACAddress(macAddress);
    eth.setSourceMACAddress(egressInterface.mac());
    eth.setEtherType(EthType.EtherType.IPV4.ethType().toShort());
    eth.setPayload(ipv4);
    if (!egressInterface.vlan().equals(VlanId.NONE)) {
      eth.setVlanID(egressInterface.vlan().toShort());
    }

    ipv4.setTtl((byte) (ipv4.getTtl() - 1));
    ipv4.setChecksum((short) 0);

    send(eth, egressInterface.connectPoint());
  }
Пример #3
0
  private void handle(Ethernet eth) {
    checkNotNull(eth);

    if (!(eth.getEtherType() == EthType.EtherType.IPV4.ethType().toShort())) {
      return;
    }

    IPv4 ipv4 = (IPv4) eth.getPayload().clone();

    Ip4Address dstIp = Ip4Address.valueOf(ipv4.getDestinationAddress());

    Interface egressInterface = interfaceService.getMatchingInterface(dstIp);

    if (egressInterface == null) {
      log.info("No egress interface found for {}", dstIp);
      return;
    }

    Optional<Host> host =
        hostService
            .getHostsByIp(dstIp)
            .stream()
            .filter(h -> h.location().equals(egressInterface.connectPoint()))
            .filter(h -> h.vlan().equals(egressInterface.vlan()))
            .findAny();

    if (host.isPresent()) {
      transformAndSend(ipv4, egressInterface, host.get().mac());
    } else {
      hostService.startMonitoringIp(dstIp);
      ipPacketCache
          .asMap()
          .compute(
              dstIp,
              (ip, queue) -> {
                if (queue == null) {
                  queue = new ConcurrentLinkedQueue();
                }
                queue.add(ipv4);
                return queue;
              });
    }
  }
Пример #4
0
  /**
   * Generates a route intent for a prefix, the next hop IP address, and the next hop MAC address.
   *
   * <p>This method will find the egress interface for the intent. Intent will match dst IP prefix
   * and rewrite dst MAC address at all other border switches, then forward packets according to dst
   * MAC address.
   *
   * @param prefix IP prefix of the route to add
   * @param nextHopIpAddress IP address of the next hop
   * @param nextHopMacAddress MAC address of the next hop
   * @return the generated intent, or null if no intent should be submitted
   */
  private MultiPointToSinglePointIntent generateRouteIntent(
      IpPrefix prefix, IpAddress nextHopIpAddress, MacAddress nextHopMacAddress) {

    // Find the attachment point (egress interface) of the next hop
    Interface egressInterface = interfaceService.getMatchingInterface(nextHopIpAddress);
    if (egressInterface == null) {
      log.warn("No outgoing interface found for {}", nextHopIpAddress);
      return null;
    }

    // Generate the intent itself
    Set<ConnectPoint> ingressPorts = new HashSet<>();
    ConnectPoint egressPort = egressInterface.connectPoint();
    log.debug("Generating intent for prefix {}, next hop mac {}", prefix, nextHopMacAddress);

    for (Interface intf : interfaceService.getInterfaces()) {
      // TODO this should be only peering interfaces
      if (!intf.connectPoint().equals(egressInterface.connectPoint())) {
        ConnectPoint srcPort = intf.connectPoint();
        ingressPorts.add(srcPort);
      }
    }

    // Match the destination IP prefix at the first hop
    TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
    if (prefix.isIp4()) {
      selector.matchEthType(Ethernet.TYPE_IPV4);
      // if it is default route, then we do not need match destination
      // IP address
      if (prefix.prefixLength() != 0) {
        selector.matchIPDst(prefix);
      }
    } else {
      selector.matchEthType(Ethernet.TYPE_IPV6);
      // if it is default route, then we do not need match destination
      // IP address
      if (prefix.prefixLength() != 0) {
        selector.matchIPv6Dst(prefix);
      }
    }

    // Rewrite the destination MAC address
    TrafficTreatment.Builder treatment =
        DefaultTrafficTreatment.builder().setEthDst(nextHopMacAddress);
    if (!egressInterface.vlan().equals(VlanId.NONE)) {
      treatment.setVlanId(egressInterface.vlan());
      // If we set VLAN ID, we have to make sure a VLAN tag exists.
      // TODO support no VLAN -> VLAN routing
      selector.matchVlanId(VlanId.ANY);
    }

    int priority = prefix.prefixLength() * PRIORITY_MULTIPLIER + PRIORITY_OFFSET;
    Key key = Key.of(prefix.toString(), appId);
    return MultiPointToSinglePointIntent.builder()
        .appId(appId)
        .key(key)
        .selector(selector.build())
        .treatment(treatment.build())
        .ingressPoints(ingressPorts)
        .egressPoint(egressPort)
        .priority(priority)
        .constraints(CONSTRAINTS)
        .build();
  }