/**
   * Constructs a BGP intent and put it into the intentList.
   *
   * <p>The purpose of this method is too simplify the setUpBgpIntents() method, and to make the
   * setUpBgpIntents() easy to read.
   *
   * @param srcVlanId ingress VlanId
   * @param dstVlanId egress VlanId
   * @param srcPrefix source IP prefix to match
   * @param dstPrefix destination IP prefix to match
   * @param srcTcpPort source TCP port to match
   * @param dstTcpPort destination TCP port to match
   * @param srcConnectPoint source connect point for PointToPointIntent
   * @param dstConnectPoint destination connect point for PointToPointIntent
   */
  private void bgpPathintentConstructor(
      VlanId srcVlanId,
      VlanId dstVlanId,
      String srcPrefix,
      String dstPrefix,
      Short srcTcpPort,
      Short dstTcpPort,
      ConnectPoint srcConnectPoint,
      ConnectPoint dstConnectPoint) {

    TrafficSelector.Builder builder =
        DefaultTrafficSelector.builder()
            .matchEthType(Ethernet.TYPE_IPV4)
            .matchIPProtocol(IPv4.PROTOCOL_TCP)
            .matchIPSrc(IpPrefix.valueOf(srcPrefix))
            .matchIPDst(IpPrefix.valueOf(dstPrefix));

    if (!srcVlanId.equals(VlanId.NONE)) {
      builder.matchVlanId(srcVlanId);
    }

    TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();

    if (!dstVlanId.equals(VlanId.NONE)) {
      treatment.setVlanId(dstVlanId);
    }

    if (srcTcpPort != null) {
      builder.matchTcpSrc(TpPort.tpPort(srcTcpPort));
    }
    if (dstTcpPort != null) {
      builder.matchTcpDst(TpPort.tpPort(dstTcpPort));
    }

    Key key =
        Key.of(
            srcPrefix.split("/")[0]
                + "-"
                + dstPrefix.split("/")[0]
                + "-"
                + ((srcTcpPort == null) ? "dst" : "src"),
            APPID);

    PointToPointIntent intent =
        PointToPointIntent.builder()
            .appId(APPID)
            .key(key)
            .selector(builder.build())
            .treatment(treatment.build())
            .ingressPoint(srcConnectPoint)
            .egressPoint(dstConnectPoint)
            .build();

    intentList.add(intent);
  }
  // Install a rule forwarding the packet to the specified port.
  private void installRule(PacketContext context, PortNumber portNumber) {
    //
    // We don't support (yet) buffer IDs in the Flow Service so
    // packet out first.
    //
    Ethernet inPkt = context.inPacket().parsed();
    TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();

    // If PacketOutOnly or ARP packet than forward directly to output port
    if (packetOutOnly || inPkt.getEtherType() == Ethernet.TYPE_ARP) {
      packetOut(context, portNumber);
      return;
    }

    //
    // If matchDstMacOnly
    //    Create flows matching dstMac only
    // Else
    //    Create flows with default matching and include configured fields
    //
    if (matchDstMacOnly) {
      selectorBuilder.matchEthDst(inPkt.getDestinationMAC());
    } else {
      selectorBuilder
          .matchInPort(context.inPacket().receivedFrom().port())
          .matchEthSrc(inPkt.getSourceMAC())
          .matchEthDst(inPkt.getDestinationMAC());

      // If configured Match Vlan ID
      if (matchVlanId && inPkt.getVlanID() != Ethernet.VLAN_UNTAGGED) {
        selectorBuilder.matchVlanId(VlanId.vlanId(inPkt.getVlanID()));
      }

      //
      // If configured and EtherType is IPv4 - Match IPv4 and
      // TCP/UDP/ICMP fields
      //
      if (matchIpv4Address && inPkt.getEtherType() == Ethernet.TYPE_IPV4) {
        IPv4 ipv4Packet = (IPv4) inPkt.getPayload();
        byte ipv4Protocol = ipv4Packet.getProtocol();
        Ip4Prefix matchIp4SrcPrefix =
            Ip4Prefix.valueOf(ipv4Packet.getSourceAddress(), Ip4Prefix.MAX_MASK_LENGTH);
        Ip4Prefix matchIp4DstPrefix =
            Ip4Prefix.valueOf(ipv4Packet.getDestinationAddress(), Ip4Prefix.MAX_MASK_LENGTH);
        selectorBuilder
            .matchEthType(Ethernet.TYPE_IPV4)
            .matchIPSrc(matchIp4SrcPrefix)
            .matchIPDst(matchIp4DstPrefix);

        if (matchIpv4Dscp) {
          byte dscp = ipv4Packet.getDscp();
          byte ecn = ipv4Packet.getEcn();
          selectorBuilder.matchIPDscp(dscp).matchIPEcn(ecn);
        }

        if (matchTcpUdpPorts && ipv4Protocol == IPv4.PROTOCOL_TCP) {
          TCP tcpPacket = (TCP) ipv4Packet.getPayload();
          selectorBuilder
              .matchIPProtocol(ipv4Protocol)
              .matchTcpSrc(tcpPacket.getSourcePort())
              .matchTcpDst(tcpPacket.getDestinationPort());
        }
        if (matchTcpUdpPorts && ipv4Protocol == IPv4.PROTOCOL_UDP) {
          UDP udpPacket = (UDP) ipv4Packet.getPayload();
          selectorBuilder
              .matchIPProtocol(ipv4Protocol)
              .matchUdpSrc(udpPacket.getSourcePort())
              .matchUdpDst(udpPacket.getDestinationPort());
        }
        if (matchIcmpFields && ipv4Protocol == IPv4.PROTOCOL_ICMP) {
          ICMP icmpPacket = (ICMP) ipv4Packet.getPayload();
          selectorBuilder
              .matchIPProtocol(ipv4Protocol)
              .matchIcmpType(icmpPacket.getIcmpType())
              .matchIcmpCode(icmpPacket.getIcmpCode());
        }
      }

      //
      // If configured and EtherType is IPv6 - Match IPv6 and
      // TCP/UDP/ICMP fields
      //
      if (matchIpv6Address && inPkt.getEtherType() == Ethernet.TYPE_IPV6) {
        IPv6 ipv6Packet = (IPv6) inPkt.getPayload();
        byte ipv6NextHeader = ipv6Packet.getNextHeader();
        Ip6Prefix matchIp6SrcPrefix =
            Ip6Prefix.valueOf(ipv6Packet.getSourceAddress(), Ip6Prefix.MAX_MASK_LENGTH);
        Ip6Prefix matchIp6DstPrefix =
            Ip6Prefix.valueOf(ipv6Packet.getDestinationAddress(), Ip6Prefix.MAX_MASK_LENGTH);
        selectorBuilder
            .matchEthType(Ethernet.TYPE_IPV6)
            .matchIPv6Src(matchIp6SrcPrefix)
            .matchIPv6Dst(matchIp6DstPrefix);

        if (matchIpv6FlowLabel) {
          selectorBuilder.matchIPv6FlowLabel(ipv6Packet.getFlowLabel());
        }

        if (matchTcpUdpPorts && ipv6NextHeader == IPv6.PROTOCOL_TCP) {
          TCP tcpPacket = (TCP) ipv6Packet.getPayload();
          selectorBuilder
              .matchIPProtocol(ipv6NextHeader)
              .matchTcpSrc(tcpPacket.getSourcePort())
              .matchTcpDst(tcpPacket.getDestinationPort());
        }
        if (matchTcpUdpPorts && ipv6NextHeader == IPv6.PROTOCOL_UDP) {
          UDP udpPacket = (UDP) ipv6Packet.getPayload();
          selectorBuilder
              .matchIPProtocol(ipv6NextHeader)
              .matchUdpSrc(udpPacket.getSourcePort())
              .matchUdpDst(udpPacket.getDestinationPort());
        }
        if (matchIcmpFields && ipv6NextHeader == IPv6.PROTOCOL_ICMP6) {
          ICMP6 icmp6Packet = (ICMP6) ipv6Packet.getPayload();
          selectorBuilder
              .matchIPProtocol(ipv6NextHeader)
              .matchIcmpv6Type(icmp6Packet.getIcmpType())
              .matchIcmpv6Code(icmp6Packet.getIcmpCode());
        }
      }
    }
    TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(portNumber).build();

    ForwardingObjective forwardingObjective =
        DefaultForwardingObjective.builder()
            .withSelector(selectorBuilder.build())
            .withTreatment(treatment)
            .withPriority(flowPriority)
            .withFlag(ForwardingObjective.Flag.VERSATILE)
            .fromApp(appId)
            .makeTemporary(flowTimeout)
            .add();

    flowObjectiveService.forward(context.inPacket().receivedFrom().deviceId(), forwardingObjective);

    //
    // If packetOutOfppTable
    //  Send packet back to the OpenFlow pipeline to match installed flow
    // Else
    //  Send packet direction on the appropriate port
    //
    if (packetOutOfppTable) {
      packetOut(context, PortNumber.TABLE);
    } else {
      packetOut(context, portNumber);
    }
  }
Beispiel #3
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();
  }