/** Request packet in via PacketService. */ private void requestPackests() { TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); selector.matchEthType(Ethernet.TYPE_IPV4); packetService.requestPackets(selector.build(), PacketPriority.REACTIVE, appId); selector.matchEthType(Ethernet.TYPE_ARP); packetService.requestPackets(selector.build(), PacketPriority.REACTIVE, appId); if (ipv6Forwarding) { selector.matchEthType(Ethernet.TYPE_IPV6); packetService.requestPackets(selector.build(), PacketPriority.REACTIVE, appId); } }
private void populateRoutingRulestoSameNode( Ip4Address vmIp, MacAddress vmMac, PortNumber port, DeviceId deviceId, long vni, String cidr) { TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder(); TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder(); // FIXME: we need to check the VNI of the dest IP also just in case... sBuilder .matchEthType(Ethernet.TYPE_IPV4) .matchIPDst(vmIp.toIpPrefix()) .matchIPSrc(IpPrefix.valueOf(cidr)) .matchTunnelId(vni); tBuilder.setEthDst(vmMac).setOutput(port); ForwardingObjective fo = DefaultForwardingObjective.builder() .withSelector(sBuilder.build()) .withTreatment(tBuilder.build()) .withPriority(EW_ROUTING_RULE_PRIORITY) .withFlag(ForwardingObjective.Flag.SPECIFIC) .fromApp(appId) .add(); flowObjectiveService.forward(deviceId, fo); }
private void removeExternalRules(OpenstackNetwork osNet, String subNetCidr) { TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder(); sBuilder .matchEthType(Ethernet.TYPE_IPV4) .matchTunnelId(Long.valueOf(osNet.segmentId())) .matchIPSrc(IpPrefix.valueOf(subNetCidr)) .matchEthDst(Constants.DEFAULT_GATEWAY_MAC); nodeService .completeNodes() .forEach( node -> { ForwardingObjective.Flag flag = node.type().equals(GATEWAY) ? ForwardingObjective.Flag.VERSATILE : ForwardingObjective.Flag.SPECIFIC; RulePopulatorUtil.removeRule( flowObjectiveService, appId, node.intBridge(), sBuilder.build(), flag, ROUTING_RULE_PRIORITY); }); }
private void populateRoutingRulestoDifferentNode( Ip4Address vmIp, long vni, DeviceId deviceId, Ip4Address hostIp, String cidr) { TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder(); TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder(); sBuilder .matchEthType(Ethernet.TYPE_IPV4) .matchTunnelId(vni) .matchIPSrc(IpPrefix.valueOf(cidr)) .matchIPDst(vmIp.toIpPrefix()); tBuilder .extension(buildExtension(deviceService, deviceId, hostIp), deviceId) .setOutput(nodeService.tunnelPort(deviceId).get()); ForwardingObjective fo = DefaultForwardingObjective.builder() .withSelector(sBuilder.build()) .withTreatment(tBuilder.build()) .withPriority(EW_ROUTING_RULE_PRIORITY) .withFlag(ForwardingObjective.Flag.SPECIFIC) .fromApp(appId) .add(); flowObjectiveService.forward(deviceId, fo); }
@Activate public void activate(ComponentContext context) { appId = coreService.registerApplication("org.onosproject.provider.host"); modified(context); providerService = providerRegistry.register(this); pktService.addProcessor(processor, 1); deviceService.addListener(deviceListener); TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder(); selectorBuilder.matchEthType(Ethernet.TYPE_ARP); pktService.requestPackets(selectorBuilder.build(), PacketPriority.CONTROL, appId); log.info("Started"); }
private void removeGatewayIcmpRule(Ip4Address gatewayIp, DeviceId deviceId) { TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder(); sBuilder .matchEthType(Ethernet.TYPE_IPV4) .matchIPProtocol(IPv4.PROTOCOL_ICMP) .matchIPDst(gatewayIp.toIpPrefix()); RulePopulatorUtil.removeRule( flowObjectiveService, appId, deviceId, sBuilder.build(), ForwardingObjective.Flag.VERSATILE, GATEWAY_ICMP_PRIORITY); }
private void populateRuleToGateway(DeviceId deviceId, GroupId groupId, long vni, String cidr) { TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder(); TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder(); sBuilder .matchEthType(Ethernet.TYPE_IPV4) .matchTunnelId(vni) .matchIPSrc(IpPrefix.valueOf(cidr)) .matchEthDst(Constants.DEFAULT_GATEWAY_MAC); tBuilder.group(groupId); ForwardingObjective fo = DefaultForwardingObjective.builder() .withSelector(sBuilder.build()) .withTreatment(tBuilder.build()) .withFlag(ForwardingObjective.Flag.SPECIFIC) .withPriority(ROUTING_RULE_PRIORITY) .fromApp(appId) .add(); flowObjectiveService.forward(deviceId, fo); }
private void populateGatewayIcmpRule(Ip4Address gatewayIp, DeviceId deviceId) { TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder(); TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder(); sBuilder .matchEthType(Ethernet.TYPE_IPV4) .matchIPProtocol(IPv4.PROTOCOL_ICMP) .matchIPDst(gatewayIp.toIpPrefix()); tBuilder.setOutput(PortNumber.CONTROLLER); ForwardingObjective fo = DefaultForwardingObjective.builder() .withSelector(sBuilder.build()) .withTreatment(tBuilder.build()) .withPriority(GATEWAY_ICMP_PRIORITY) .withFlag(ForwardingObjective.Flag.VERSATILE) .fromApp(appId) .add(); flowObjectiveService.forward(deviceId, fo); }
private void removeRoutingRules(Host host, Set<OpenstackSubnet> osSubNets) { String osSubNetId = host.annotations().value(SUBNET_ID); if (osSubNetId == null) { return; } Map<String, String> vniMap = new HashMap<>(); openstackService.networks().stream().forEach(n -> vniMap.put(n.id(), n.segmentId())); osSubNets .stream() .filter(osSubNet -> !osSubNet.id().equals(osSubNetId)) .forEach( osSubNet -> { TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder(); sBuilder .matchEthType(Ethernet.TYPE_IPV4) .matchIPDst(host.ipAddresses().stream().findFirst().get().toIpPrefix()) .matchIPSrc(IpPrefix.valueOf(osSubNet.cidr())) .matchTunnelId(Long.valueOf(vniMap.get(osSubNet.networkId()))); nodeService .completeNodes() .stream() .filter(node -> node.type().equals(COMPUTE)) .forEach( node -> RulePopulatorUtil.removeRule( flowObjectiveService, appId, node.intBridge(), sBuilder.build(), ForwardingObjective.Flag.SPECIFIC, EW_ROUTING_RULE_PRIORITY)); }); log.debug("Removed routing rule from {} to {}", host, osSubNets); }
private void populateGatewayToController(long vni, String subNetCidr) { TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder(); TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder(); sBuilder .matchEthType(Ethernet.TYPE_IPV4) .matchTunnelId(vni) .matchIPSrc(IpPrefix.valueOf(subNetCidr)) .matchEthDst(Constants.DEFAULT_GATEWAY_MAC); tBuilder.setOutput(PortNumber.CONTROLLER); ForwardingObjective fo = DefaultForwardingObjective.builder() .withSelector(sBuilder.build()) .withTreatment(tBuilder.build()) .withFlag(ForwardingObjective.Flag.VERSATILE) .withPriority(ROUTING_RULE_PRIORITY) .fromApp(appId) .add(); gatewayService .getGatewayDeviceIds() .forEach(deviceId -> flowObjectiveService.forward(deviceId, fo)); }
// 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); } }
@Override // Dell switches need ETH_DST based match condition in all IP table entries. // So this method overrides the default spring-open behavior and adds // ETH_DST match condition while pushing IP table flow rules protected Collection<FlowRule> processSpecific(ForwardingObjective fwd) { log.debug("Processing specific"); TrafficSelector selector = fwd.selector(); EthTypeCriterion ethType = (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE); if ((ethType == null) || ((((short) ethType.ethType()) != Ethernet.TYPE_IPV4) && (((short) ethType.ethType()) != Ethernet.MPLS_UNICAST))) { log.debug("processSpecific: Unsupported " + "forwarding objective criteraia"); fail(fwd, ObjectiveError.UNSUPPORTED); return Collections.emptySet(); } TrafficSelector.Builder filteredSelectorBuilder = DefaultTrafficSelector.builder(); int forTableId = -1; if (((short) ethType.ethType()) == Ethernet.TYPE_IPV4) { if (deviceTMac == null) { log.debug( "processSpecific: ETH_DST filtering " + "objective is not set which is required " + "before sending a IPv4 forwarding objective"); // TODO: Map the error to more appropriate error code. fail(fwd, ObjectiveError.DEVICEMISSING); return Collections.emptySet(); } filteredSelectorBuilder = filteredSelectorBuilder .matchEthType(Ethernet.TYPE_IPV4) .matchEthDst(deviceTMac) .matchIPDst(((IPCriterion) selector.getCriterion(Criterion.Type.IPV4_DST)).ip()); forTableId = ipv4UnicastTableId; log.debug("processing IPv4 specific forwarding objective"); } else { filteredSelectorBuilder = filteredSelectorBuilder .matchEthType(Ethernet.MPLS_UNICAST) .matchMplsLabel( ((MplsCriterion) selector.getCriterion(Criterion.Type.MPLS_LABEL)).label()); // TODO: Add Match for BoS // if (selector.getCriterion(Criterion.Type.MPLS_BOS) != null) { // } forTableId = mplsTableId; log.debug("processing MPLS specific forwarding objective"); } TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder(); if (fwd.treatment() != null) { for (Instruction i : fwd.treatment().allInstructions()) { treatmentBuilder.add(i); } } if (fwd.nextId() != null) { NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId()); if (next != null) { GroupKey key = appKryo.deserialize(next.data()); Group group = groupService.getGroup(deviceId, key); if (group == null) { log.warn("The group left!"); fail(fwd, ObjectiveError.GROUPMISSING); return Collections.emptySet(); } treatmentBuilder.group(group.id()); log.debug("Adding OUTGROUP action"); } else { log.warn("processSpecific: No associated next objective object"); fail(fwd, ObjectiveError.GROUPMISSING); return Collections.emptySet(); } } TrafficSelector filteredSelector = filteredSelectorBuilder.build(); TrafficTreatment treatment = treatmentBuilder.transition(aclTableId).build(); FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() .fromApp(fwd.appId()) .withPriority(fwd.priority()) .forDevice(deviceId) .withSelector(filteredSelector) .withTreatment(treatment); if (fwd.permanent()) { ruleBuilder.makePermanent(); } else { ruleBuilder.makeTemporary(fwd.timeout()); } ruleBuilder.forTable(forTableId); return Collections.singletonList(ruleBuilder.build()); }
/** * 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(); }