Committed by
Gerrit Code Review
[CORD-46] Implement L2 switching in Segment Routing
DONE
- Update SpringOpenTTP to support bridging table emulation
- Populate low priority subnet broadcast entry for bridging table
- Move IP entry population to host event handler as well
- Update ArpHandler to handle intra-rack ARP forwarding/flooding
- Move TTL_OUT action from IP table to corresponding group
Since hardware does not support TTL_OUT in the IP table
- Populate entries to bridging table (MAC learning)
- Emulate src mac table
Not in this submission
- Emulate src-mac table behavior
- Pop vlan in the group instead of the flow
Change-Id: Ib69357c1889ccddaa4daa272d9f5843790ee1a3c
Showing
7 changed files
with
217 additions
and
80 deletions
| ... | @@ -20,10 +20,10 @@ import org.onlab.packet.Ethernet; | ... | @@ -20,10 +20,10 @@ import org.onlab.packet.Ethernet; |
| 20 | import org.onlab.packet.Ip4Address; | 20 | import org.onlab.packet.Ip4Address; |
| 21 | import org.onlab.packet.IpAddress; | 21 | import org.onlab.packet.IpAddress; |
| 22 | import org.onlab.packet.MacAddress; | 22 | import org.onlab.packet.MacAddress; |
| 23 | +import org.onlab.packet.VlanId; | ||
| 23 | import org.onosproject.net.ConnectPoint; | 24 | import org.onosproject.net.ConnectPoint; |
| 24 | import org.onosproject.net.DeviceId; | 25 | import org.onosproject.net.DeviceId; |
| 25 | import org.onosproject.net.Host; | 26 | import org.onosproject.net.Host; |
| 26 | -import org.onosproject.net.Port; | ||
| 27 | import org.onosproject.net.PortNumber; | 27 | import org.onosproject.net.PortNumber; |
| 28 | import org.onosproject.net.flow.DefaultTrafficTreatment; | 28 | import org.onosproject.net.flow.DefaultTrafficTreatment; |
| 29 | import org.onosproject.net.flow.TrafficTreatment; | 29 | import org.onosproject.net.flow.TrafficTreatment; |
| ... | @@ -60,12 +60,21 @@ public class ArpHandler { | ... | @@ -60,12 +60,21 @@ public class ArpHandler { |
| 60 | 60 | ||
| 61 | /** | 61 | /** |
| 62 | * Processes incoming ARP packets. | 62 | * Processes incoming ARP packets. |
| 63 | + * | ||
| 63 | * If it is an ARP request to router itself or known hosts, | 64 | * If it is an ARP request to router itself or known hosts, |
| 64 | * then it sends ARP response. | 65 | * then it sends ARP response. |
| 65 | * If it is an ARP request to unknown hosts in its own subnet, | 66 | * If it is an ARP request to unknown hosts in its own subnet, |
| 66 | * then it flood the ARP request to the ports. | 67 | * then it flood the ARP request to the ports. |
| 67 | * If it is an ARP response, then set a flow rule for the host | 68 | * If it is an ARP response, then set a flow rule for the host |
| 68 | * and forward any IP packets to the host in the packet buffer to the host. | 69 | * and forward any IP packets to the host in the packet buffer to the host. |
| 70 | + * <p> | ||
| 71 | + * Note: We handles all ARP packet in, even for those ARP packets between | ||
| 72 | + * hosts in the same subnet. | ||
| 73 | + * For an ARP packet with broadcast destination MAC, | ||
| 74 | + * some switches pipelines will send it to the controller due to table miss, | ||
| 75 | + * other swithches will flood the packets directly in the data plane without | ||
| 76 | + * packet in. | ||
| 77 | + * We can deal with both cases. | ||
| 69 | * | 78 | * |
| 70 | * @param pkt incoming packet | 79 | * @param pkt incoming packet |
| 71 | */ | 80 | */ |
| ... | @@ -86,29 +95,56 @@ public class ArpHandler { | ... | @@ -86,29 +95,56 @@ public class ArpHandler { |
| 86 | if (arp.getOpCode() == ARP.OP_REQUEST) { | 95 | if (arp.getOpCode() == ARP.OP_REQUEST) { |
| 87 | handleArpRequest(deviceId, connectPoint, ethernet); | 96 | handleArpRequest(deviceId, connectPoint, ethernet); |
| 88 | } else { | 97 | } else { |
| 89 | - srManager.ipHandler.forwardPackets(deviceId, hostIpAddress); | 98 | + handleArpReply(deviceId, connectPoint, ethernet); |
| 90 | } | 99 | } |
| 91 | } | 100 | } |
| 92 | 101 | ||
| 93 | private void handleArpRequest(DeviceId deviceId, ConnectPoint inPort, Ethernet payload) { | 102 | private void handleArpRequest(DeviceId deviceId, ConnectPoint inPort, Ethernet payload) { |
| 94 | ARP arpRequest = (ARP) payload.getPayload(); | 103 | ARP arpRequest = (ARP) payload.getPayload(); |
| 104 | + VlanId vlanId = VlanId.vlanId(payload.getVlanID()); | ||
| 95 | HostId targetHostId = HostId.hostId(MacAddress.valueOf( | 105 | HostId targetHostId = HostId.hostId(MacAddress.valueOf( |
| 96 | - arpRequest.getTargetHardwareAddress())); | 106 | + arpRequest.getTargetHardwareAddress()), |
| 107 | + vlanId); | ||
| 97 | 108 | ||
| 98 | - // ARP request for router | 109 | + // ARP request for router. Send ARP reply. |
| 99 | if (isArpReqForRouter(deviceId, arpRequest)) { | 110 | if (isArpReqForRouter(deviceId, arpRequest)) { |
| 100 | Ip4Address targetAddress = Ip4Address.valueOf(arpRequest.getTargetProtocolAddress()); | 111 | Ip4Address targetAddress = Ip4Address.valueOf(arpRequest.getTargetProtocolAddress()); |
| 101 | - | 112 | + sendArpResponse(arpRequest, config.getRouterMacForAGatewayIp(targetAddress), vlanId); |
| 102 | - sendArpResponse(arpRequest, config.getRouterMacForAGatewayIp(targetAddress)); | ||
| 103 | } else { | 113 | } else { |
| 104 | Host targetHost = srManager.hostService.getHost(targetHostId); | 114 | Host targetHost = srManager.hostService.getHost(targetHostId); |
| 105 | - // ARP request for known hosts | 115 | + // ARP request for known hosts. Send proxy ARP reply on behalf of the target. |
| 106 | if (targetHost != null) { | 116 | if (targetHost != null) { |
| 107 | - sendArpResponse(arpRequest, targetHost.mac()); | 117 | + removeVlanAndForward(payload, targetHost.location()); |
| 118 | + // ARP request for unknown host in the subnet. Flood in the subnet. | ||
| 119 | + } else { | ||
| 120 | + removeVlanAndFlood(payload, inPort); | ||
| 121 | + } | ||
| 122 | + } | ||
| 123 | + } | ||
| 108 | 124 | ||
| 109 | - // ARP request for unknown host in the subnet | 125 | + private void handleArpReply(DeviceId deviceId, ConnectPoint inPort, Ethernet payload) { |
| 110 | - } else if (isArpReqForSubnet(deviceId, arpRequest)) { | 126 | + ARP arpReply = (ARP) payload.getPayload(); |
| 111 | - flood(payload, inPort); | 127 | + VlanId vlanId = VlanId.vlanId(payload.getVlanID()); |
| 128 | + HostId targetHostId = HostId.hostId(MacAddress.valueOf( | ||
| 129 | + arpReply.getTargetHardwareAddress()), | ||
| 130 | + vlanId); | ||
| 131 | + | ||
| 132 | + // ARP reply for router. Process all pending IP packets. | ||
| 133 | + if (isArpReqForRouter(deviceId, arpReply)) { | ||
| 134 | + Ip4Address hostIpAddress = Ip4Address.valueOf(arpReply.getSenderProtocolAddress()); | ||
| 135 | + srManager.ipHandler.forwardPackets(deviceId, hostIpAddress); | ||
| 136 | + } else { | ||
| 137 | + Host targetHost = srManager.hostService.getHost(targetHostId); | ||
| 138 | + // ARP reply for known hosts. Forward to the host. | ||
| 139 | + if (targetHost != null) { | ||
| 140 | + removeVlanAndForward(payload, targetHost.location()); | ||
| 141 | + // ARP reply for unknown host, Flood in the subnet. | ||
| 142 | + } else { | ||
| 143 | + // Don't flood to non-edge ports | ||
| 144 | + if (vlanId.equals(VlanId.vlanId(srManager.ASSIGNED_VLAN_NO_SUBNET))) { | ||
| 145 | + return; | ||
| 146 | + } | ||
| 147 | + removeVlanAndFlood(payload, inPort); | ||
| 112 | } | 148 | } |
| 113 | } | 149 | } |
| 114 | } | 150 | } |
| ... | @@ -126,14 +162,6 @@ public class ArpHandler { | ... | @@ -126,14 +162,6 @@ public class ArpHandler { |
| 126 | return false; | 162 | return false; |
| 127 | } | 163 | } |
| 128 | 164 | ||
| 129 | - private boolean isArpReqForSubnet(DeviceId deviceId, ARP arpRequest) { | ||
| 130 | - return config.getSubnets(deviceId).stream() | ||
| 131 | - .anyMatch((prefix)-> | ||
| 132 | - prefix.contains(Ip4Address. | ||
| 133 | - valueOf(arpRequest. | ||
| 134 | - getTargetProtocolAddress()))); | ||
| 135 | - } | ||
| 136 | - | ||
| 137 | /** | 165 | /** |
| 138 | * Sends an APR request for the target IP address to all ports except in-port. | 166 | * Sends an APR request for the target IP address to all ports except in-port. |
| 139 | * | 167 | * |
| ... | @@ -170,11 +198,10 @@ public class ArpHandler { | ... | @@ -170,11 +198,10 @@ public class ArpHandler { |
| 170 | .setSourceMACAddress(senderMacAddress) | 198 | .setSourceMACAddress(senderMacAddress) |
| 171 | .setEtherType(Ethernet.TYPE_ARP).setPayload(arpRequest); | 199 | .setEtherType(Ethernet.TYPE_ARP).setPayload(arpRequest); |
| 172 | 200 | ||
| 173 | - flood(eth, inPort); | 201 | + removeVlanAndFlood(eth, inPort); |
| 174 | } | 202 | } |
| 175 | 203 | ||
| 176 | - private void sendArpResponse(ARP arpRequest, MacAddress targetMac) { | 204 | + private void sendArpResponse(ARP arpRequest, MacAddress targetMac, VlanId vlanId) { |
| 177 | - | ||
| 178 | ARP arpReply = new ARP(); | 205 | ARP arpReply = new ARP(); |
| 179 | arpReply.setHardwareType(ARP.HW_TYPE_ETHERNET) | 206 | arpReply.setHardwareType(ARP.HW_TYPE_ETHERNET) |
| 180 | .setProtocolType(ARP.PROTO_TYPE_IP) | 207 | .setProtocolType(ARP.PROTO_TYPE_IP) |
| ... | @@ -193,8 +220,9 @@ public class ArpHandler { | ... | @@ -193,8 +220,9 @@ public class ArpHandler { |
| 193 | .setEtherType(Ethernet.TYPE_ARP).setPayload(arpReply); | 220 | .setEtherType(Ethernet.TYPE_ARP).setPayload(arpReply); |
| 194 | 221 | ||
| 195 | 222 | ||
| 196 | - HostId dstId = HostId.hostId(MacAddress.valueOf( | 223 | + HostId dstId = HostId.hostId( |
| 197 | - arpReply.getTargetHardwareAddress())); | 224 | + MacAddress.valueOf(arpReply.getTargetHardwareAddress()), |
| 225 | + vlanId); | ||
| 198 | Host dst = srManager.hostService.getHost(dstId); | 226 | Host dst = srManager.hostService.getHost(dstId); |
| 199 | if (dst == null) { | 227 | if (dst == null) { |
| 200 | log.warn("Cannot send ARP response to unknown device"); | 228 | log.warn("Cannot send ARP response to unknown device"); |
| ... | @@ -209,19 +237,51 @@ public class ArpHandler { | ... | @@ -209,19 +237,51 @@ public class ArpHandler { |
| 209 | srManager.packetService.emit(packet); | 237 | srManager.packetService.emit(packet); |
| 210 | } | 238 | } |
| 211 | 239 | ||
| 212 | - private void flood(Ethernet request, ConnectPoint inPort) { | 240 | + /** |
| 213 | - TrafficTreatment.Builder builder; | 241 | + * Remove VLAN tag and flood to all ports in the same subnet. |
| 214 | - ByteBuffer buf = ByteBuffer.wrap(request.serialize()); | 242 | + * |
| 215 | - | 243 | + * @param packet packet to be flooded |
| 216 | - for (Port port: srManager.deviceService.getPorts(inPort.deviceId())) { | 244 | + * @param inPort where the packet comes from |
| 217 | - if (!port.number().equals(inPort.port()) && | 245 | + */ |
| 218 | - port.number().toLong() > 0) { | 246 | + private void removeVlanAndFlood(Ethernet packet, ConnectPoint inPort) { |
| 219 | - builder = DefaultTrafficTreatment.builder(); | 247 | + Ip4Address targetProtocolAddress = Ip4Address.valueOf( |
| 220 | - builder.setOutput(port.number()); | 248 | + ((ARP) packet.getPayload()).getTargetProtocolAddress() |
| 221 | - srManager.packetService.emit(new DefaultOutboundPacket(inPort.deviceId(), | 249 | + ); |
| 222 | - builder.build(), buf)); | 250 | + |
| 223 | - } | 251 | + srManager.deviceConfiguration.getSubnetPortsMap(inPort.deviceId()).forEach((subnet, ports) -> { |
| 252 | + if (subnet.contains(targetProtocolAddress)) { | ||
| 253 | + ports.stream() | ||
| 254 | + .filter(port -> port != inPort.port()) | ||
| 255 | + .forEach(port -> { | ||
| 256 | + removeVlanAndForward(packet, new ConnectPoint(inPort.deviceId(), port)); | ||
| 257 | + }); | ||
| 224 | } | 258 | } |
| 259 | + }); | ||
| 225 | } | 260 | } |
| 226 | 261 | ||
| 262 | + /** | ||
| 263 | + * Remove VLAN tag and packet out to given port. | ||
| 264 | + * | ||
| 265 | + * Note: In current implementation, we expect all communication with | ||
| 266 | + * end hosts within a subnet to be untagged. | ||
| 267 | + * <p> | ||
| 268 | + * For those pipelines that internally assigns a VLAN, the VLAN tag will be | ||
| 269 | + * removed before egress. | ||
| 270 | + * <p> | ||
| 271 | + * For those pipelines that do not assign internal VLAN, the packet remains | ||
| 272 | + * untagged. | ||
| 273 | + * | ||
| 274 | + * @param packet packet to be forwarded | ||
| 275 | + * @param outPort where the packet should be forwarded | ||
| 276 | + */ | ||
| 277 | + private void removeVlanAndForward(Ethernet packet, ConnectPoint outPort) { | ||
| 278 | + packet.setEtherType(Ethernet.TYPE_ARP); | ||
| 279 | + packet.setVlanID(Ethernet.VLAN_UNTAGGED); | ||
| 280 | + ByteBuffer buf = ByteBuffer.wrap(packet.serialize()); | ||
| 281 | + | ||
| 282 | + TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder(); | ||
| 283 | + tbuilder.setOutput(outPort.port()); | ||
| 284 | + srManager.packetService.emit(new DefaultOutboundPacket(outPort.deviceId(), | ||
| 285 | + tbuilder.build(), buf)); | ||
| 286 | + } | ||
| 227 | } | 287 | } | ... | ... |
| ... | @@ -105,8 +105,17 @@ public class IcmpHandler { | ... | @@ -105,8 +105,17 @@ public class IcmpHandler { |
| 105 | } | 105 | } |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | + /** | ||
| 109 | + * Sends an ICMP reply message. | ||
| 110 | + * | ||
| 111 | + * Note: we assume that packets sending from the edge switches to the hosts | ||
| 112 | + * have untagged VLAN. | ||
| 113 | + * @param icmpRequest the original ICMP request | ||
| 114 | + * @param outport the output port where the ICMP reply should be sent to | ||
| 115 | + */ | ||
| 108 | private void sendICMPResponse(Ethernet icmpRequest, ConnectPoint outport) { | 116 | private void sendICMPResponse(Ethernet icmpRequest, ConnectPoint outport) { |
| 109 | - | 117 | + // Note: We assume that packets arrive at the edge switches have |
| 118 | + // untagged VLAN. | ||
| 110 | Ethernet icmpReplyEth = new Ethernet(); | 119 | Ethernet icmpReplyEth = new Ethernet(); |
| 111 | 120 | ||
| 112 | IPv4 icmpRequestIpv4 = (IPv4) icmpRequest.getPayload(); | 121 | IPv4 icmpRequestIpv4 = (IPv4) icmpRequest.getPayload(); |
| ... | @@ -129,7 +138,6 @@ public class IcmpHandler { | ... | @@ -129,7 +138,6 @@ public class IcmpHandler { |
| 129 | icmpReplyEth.setEtherType(Ethernet.TYPE_IPV4); | 138 | icmpReplyEth.setEtherType(Ethernet.TYPE_IPV4); |
| 130 | icmpReplyEth.setDestinationMACAddress(icmpRequest.getSourceMACAddress()); | 139 | icmpReplyEth.setDestinationMACAddress(icmpRequest.getSourceMACAddress()); |
| 131 | icmpReplyEth.setSourceMACAddress(icmpRequest.getDestinationMACAddress()); | 140 | icmpReplyEth.setSourceMACAddress(icmpRequest.getDestinationMACAddress()); |
| 132 | - icmpReplyEth.setVlanID(icmpRequest.getVlanID()); | ||
| 133 | 141 | ||
| 134 | Ip4Address destIpAddress = Ip4Address.valueOf(icmpReplyIpv4.getDestinationAddress()); | 142 | Ip4Address destIpAddress = Ip4Address.valueOf(icmpReplyIpv4.getDestinationAddress()); |
| 135 | Ip4Address destRouterAddress = config.getRouterIpAddressForASubnetHost(destIpAddress); | 143 | Ip4Address destRouterAddress = config.getRouterIpAddressForASubnetHost(destIpAddress); | ... | ... |
| ... | @@ -55,7 +55,6 @@ import java.util.concurrent.atomic.AtomicLong; | ... | @@ -55,7 +55,6 @@ import java.util.concurrent.atomic.AtomicLong; |
| 55 | import static com.google.common.base.Preconditions.checkNotNull; | 55 | import static com.google.common.base.Preconditions.checkNotNull; |
| 56 | 56 | ||
| 57 | public class RoutingRulePopulator { | 57 | public class RoutingRulePopulator { |
| 58 | - | ||
| 59 | private static final Logger log = LoggerFactory | 58 | private static final Logger log = LoggerFactory |
| 60 | .getLogger(RoutingRulePopulator.class); | 59 | .getLogger(RoutingRulePopulator.class); |
| 61 | 60 | ||
| ... | @@ -105,13 +104,45 @@ public class RoutingRulePopulator { | ... | @@ -105,13 +104,45 @@ public class RoutingRulePopulator { |
| 105 | */ | 104 | */ |
| 106 | public void populateIpRuleForHost(DeviceId deviceId, Ip4Address hostIp, | 105 | public void populateIpRuleForHost(DeviceId deviceId, Ip4Address hostIp, |
| 107 | MacAddress hostMac, PortNumber outPort) { | 106 | MacAddress hostMac, PortNumber outPort) { |
| 108 | - MacAddress deviceMac; | 107 | + log.debug("Populate IP table entry for host {} at {}:{}", |
| 108 | + hostIp, deviceId, outPort); | ||
| 109 | + ForwardingObjective.Builder fwdBuilder; | ||
| 109 | try { | 110 | try { |
| 110 | - deviceMac = config.getDeviceMac(deviceId); | 111 | + fwdBuilder = getForwardingObjectiveBuilder( |
| 112 | + deviceId, hostIp, hostMac, outPort); | ||
| 111 | } catch (DeviceConfigNotFoundException e) { | 113 | } catch (DeviceConfigNotFoundException e) { |
| 112 | log.warn(e.getMessage() + " Aborting populateIpRuleForHost."); | 114 | log.warn(e.getMessage() + " Aborting populateIpRuleForHost."); |
| 113 | return; | 115 | return; |
| 114 | } | 116 | } |
| 117 | + srManager.flowObjectiveService. | ||
| 118 | + forward(deviceId, fwdBuilder.add(new SRObjectiveContext(deviceId, | ||
| 119 | + SRObjectiveContext.ObjectiveType.FORWARDING))); | ||
| 120 | + rulePopulationCounter.incrementAndGet(); | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + public void revokeIpRuleForHost(DeviceId deviceId, Ip4Address hostIp, | ||
| 124 | + MacAddress hostMac, PortNumber outPort) { | ||
| 125 | + log.debug("Revoke IP table entry for host {} at {}:{}", | ||
| 126 | + hostIp, deviceId, outPort); | ||
| 127 | + ForwardingObjective.Builder fwdBuilder; | ||
| 128 | + try { | ||
| 129 | + fwdBuilder = getForwardingObjectiveBuilder( | ||
| 130 | + deviceId, hostIp, hostMac, outPort); | ||
| 131 | + } catch (DeviceConfigNotFoundException e) { | ||
| 132 | + log.warn(e.getMessage() + " Aborting revokeIpRuleForHost."); | ||
| 133 | + return; | ||
| 134 | + } | ||
| 135 | + srManager.flowObjectiveService. | ||
| 136 | + forward(deviceId, fwdBuilder.remove(new SRObjectiveContext(deviceId, | ||
| 137 | + SRObjectiveContext.ObjectiveType.FORWARDING))); | ||
| 138 | + } | ||
| 139 | + | ||
| 140 | + private ForwardingObjective.Builder getForwardingObjectiveBuilder( | ||
| 141 | + DeviceId deviceId, Ip4Address hostIp, | ||
| 142 | + MacAddress hostMac, PortNumber outPort) | ||
| 143 | + throws DeviceConfigNotFoundException { | ||
| 144 | + MacAddress deviceMac; | ||
| 145 | + deviceMac = config.getDeviceMac(deviceId); | ||
| 115 | 146 | ||
| 116 | TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder(); | 147 | TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder(); |
| 117 | TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder(); | 148 | TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder(); |
| ... | @@ -127,19 +158,10 @@ public class RoutingRulePopulator { | ... | @@ -127,19 +158,10 @@ public class RoutingRulePopulator { |
| 127 | TrafficTreatment treatment = tbuilder.build(); | 158 | TrafficTreatment treatment = tbuilder.build(); |
| 128 | TrafficSelector selector = sbuilder.build(); | 159 | TrafficSelector selector = sbuilder.build(); |
| 129 | 160 | ||
| 130 | - ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective | 161 | + return DefaultForwardingObjective.builder() |
| 131 | - .builder().fromApp(srManager.appId).makePermanent() | 162 | + .fromApp(srManager.appId).makePermanent() |
| 132 | .withSelector(selector).withTreatment(treatment) | 163 | .withSelector(selector).withTreatment(treatment) |
| 133 | .withPriority(100).withFlag(ForwardingObjective.Flag.SPECIFIC); | 164 | .withPriority(100).withFlag(ForwardingObjective.Flag.SPECIFIC); |
| 134 | - | ||
| 135 | - log.debug("Installing IPv4 forwarding objective " | ||
| 136 | - + "for host {} in switch {}", hostIp, deviceId); | ||
| 137 | - srManager.flowObjectiveService. | ||
| 138 | - forward(deviceId, | ||
| 139 | - fwdBuilder. | ||
| 140 | - add(new SRObjectiveContext(deviceId, | ||
| 141 | - SRObjectiveContext.ObjectiveType.FORWARDING))); | ||
| 142 | - rulePopulationCounter.incrementAndGet(); | ||
| 143 | } | 165 | } |
| 144 | 166 | ||
| 145 | /** | 167 | /** |
| ... | @@ -186,26 +208,25 @@ public class RoutingRulePopulator { | ... | @@ -186,26 +208,25 @@ public class RoutingRulePopulator { |
| 186 | } | 208 | } |
| 187 | 209 | ||
| 188 | TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder(); | 210 | TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder(); |
| 189 | - TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder(); | ||
| 190 | - | ||
| 191 | sbuilder.matchIPDst(ipPrefix); | 211 | sbuilder.matchIPDst(ipPrefix); |
| 192 | sbuilder.matchEthType(Ethernet.TYPE_IPV4); | 212 | sbuilder.matchEthType(Ethernet.TYPE_IPV4); |
| 213 | + TrafficSelector selector = sbuilder.build(); | ||
| 193 | 214 | ||
| 194 | - NeighborSet ns = null; | 215 | + TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder(); |
| 216 | + NeighborSet ns; | ||
| 217 | + TrafficTreatment treatment; | ||
| 195 | 218 | ||
| 196 | // If the next hop is the same as the final destination, then MPLS label | 219 | // If the next hop is the same as the final destination, then MPLS label |
| 197 | // is not set. | 220 | // is not set. |
| 198 | if (nextHops.size() == 1 && nextHops.toArray()[0].equals(destSw)) { | 221 | if (nextHops.size() == 1 && nextHops.toArray()[0].equals(destSw)) { |
| 199 | - tbuilder.deferred().decNwTtl(); | 222 | + tbuilder.immediate().decNwTtl(); |
| 200 | ns = new NeighborSet(nextHops); | 223 | ns = new NeighborSet(nextHops); |
| 224 | + treatment = tbuilder.build(); | ||
| 201 | } else { | 225 | } else { |
| 202 | - tbuilder.deferred().copyTtlOut(); | ||
| 203 | ns = new NeighborSet(nextHops, segmentId); | 226 | ns = new NeighborSet(nextHops, segmentId); |
| 227 | + treatment = null; | ||
| 204 | } | 228 | } |
| 205 | 229 | ||
| 206 | - TrafficTreatment treatment = tbuilder.build(); | ||
| 207 | - TrafficSelector selector = sbuilder.build(); | ||
| 208 | - | ||
| 209 | if (srManager.getNextObjectiveId(deviceId, ns) <= 0) { | 230 | if (srManager.getNextObjectiveId(deviceId, ns) <= 0) { |
| 210 | log.warn("No next objective in {} for ns: {}", deviceId, ns); | 231 | log.warn("No next objective in {} for ns: {}", deviceId, ns); |
| 211 | return false; | 232 | return false; |
| ... | @@ -216,10 +237,12 @@ public class RoutingRulePopulator { | ... | @@ -216,10 +237,12 @@ public class RoutingRulePopulator { |
| 216 | .fromApp(srManager.appId) | 237 | .fromApp(srManager.appId) |
| 217 | .makePermanent() | 238 | .makePermanent() |
| 218 | .nextStep(srManager.getNextObjectiveId(deviceId, ns)) | 239 | .nextStep(srManager.getNextObjectiveId(deviceId, ns)) |
| 219 | - .withTreatment(treatment) | ||
| 220 | .withSelector(selector) | 240 | .withSelector(selector) |
| 221 | .withPriority(100) | 241 | .withPriority(100) |
| 222 | .withFlag(ForwardingObjective.Flag.SPECIFIC); | 242 | .withFlag(ForwardingObjective.Flag.SPECIFIC); |
| 243 | + if (treatment != null) { | ||
| 244 | + fwdBuilder.withTreatment(treatment); | ||
| 245 | + } | ||
| 223 | log.debug("Installing IPv4 forwarding objective " | 246 | log.debug("Installing IPv4 forwarding objective " |
| 224 | + "for router IP/subnet {} in switch {}", | 247 | + "for router IP/subnet {} in switch {}", |
| 225 | ipPrefix, | 248 | ipPrefix, |
| ... | @@ -423,8 +446,6 @@ public class RoutingRulePopulator { | ... | @@ -423,8 +446,6 @@ public class RoutingRulePopulator { |
| 423 | ? VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET) | 446 | ? VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET) |
| 424 | : srManager.getSubnetAssignedVlanId(deviceId, portSubnet); | 447 | : srManager.getSubnetAssignedVlanId(deviceId, portSubnet); |
| 425 | 448 | ||
| 426 | - | ||
| 427 | - | ||
| 428 | FilteringObjective.Builder fob = DefaultFilteringObjective.builder(); | 449 | FilteringObjective.Builder fob = DefaultFilteringObjective.builder(); |
| 429 | fob.withKey(Criteria.matchInPort(port.number())) | 450 | fob.withKey(Criteria.matchInPort(port.number())) |
| 430 | .addCondition(Criteria.matchEthDst(deviceMac)) | 451 | .addCondition(Criteria.matchEthDst(deviceMac)) |
| ... | @@ -469,14 +490,14 @@ public class RoutingRulePopulator { | ... | @@ -469,14 +490,14 @@ public class RoutingRulePopulator { |
| 469 | Set<Ip4Address> allIps = new HashSet<Ip4Address>(config.getPortIPs(deviceId)); | 490 | Set<Ip4Address> allIps = new HashSet<Ip4Address>(config.getPortIPs(deviceId)); |
| 470 | allIps.add(routerIp); | 491 | allIps.add(routerIp); |
| 471 | for (Ip4Address ipaddr : allIps) { | 492 | for (Ip4Address ipaddr : allIps) { |
| 472 | - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | 493 | + TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder(); |
| 473 | - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); | 494 | + TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder(); |
| 474 | - selector.matchEthType(Ethernet.TYPE_IPV4); | 495 | + sbuilder.matchEthType(Ethernet.TYPE_IPV4); |
| 475 | - selector.matchIPDst(IpPrefix.valueOf(ipaddr, | 496 | + sbuilder.matchIPDst(IpPrefix.valueOf(ipaddr, |
| 476 | IpPrefix.MAX_INET_MASK_LENGTH)); | 497 | IpPrefix.MAX_INET_MASK_LENGTH)); |
| 477 | - treatment.setOutput(PortNumber.CONTROLLER); | 498 | + tbuilder.setOutput(PortNumber.CONTROLLER); |
| 478 | - puntIp.withSelector(selector.build()); | 499 | + puntIp.withSelector(sbuilder.build()); |
| 479 | - puntIp.withTreatment(treatment.build()); | 500 | + puntIp.withTreatment(tbuilder.build()); |
| 480 | puntIp.withFlag(Flag.VERSATILE) | 501 | puntIp.withFlag(Flag.VERSATILE) |
| 481 | .withPriority(HIGHEST_PRIORITY) | 502 | .withPriority(HIGHEST_PRIORITY) |
| 482 | .makePermanent() | 503 | .makePermanent() |
| ... | @@ -489,6 +510,48 @@ public class RoutingRulePopulator { | ... | @@ -489,6 +510,48 @@ public class RoutingRulePopulator { |
| 489 | } | 510 | } |
| 490 | } | 511 | } |
| 491 | 512 | ||
| 513 | + /** | ||
| 514 | + * Populates a forwarding objective to send packets that miss other high | ||
| 515 | + * priority Bridging Table entries to a group that contains all ports of | ||
| 516 | + * its subnet. | ||
| 517 | + * | ||
| 518 | + * Note: We assume that packets sending from the edge switches to the hosts | ||
| 519 | + * have untagged VLAN. | ||
| 520 | + * The VLAN tag will be popped later in the flooding group. | ||
| 521 | + * | ||
| 522 | + * @param deviceId switch ID to set the rules | ||
| 523 | + */ | ||
| 524 | + public void populateSubnetBroadcastRule(DeviceId deviceId) { | ||
| 525 | + config.getSubnets(deviceId).forEach(subnet -> { | ||
| 526 | + int nextId = srManager.getSubnetNextObjectiveId(deviceId, subnet); | ||
| 527 | + VlanId vlanId = srManager.getSubnetAssignedVlanId(deviceId, subnet); | ||
| 528 | + | ||
| 529 | + /* Driver should treat objective with MacAddress.NONE as the | ||
| 530 | + * subnet broadcast rule | ||
| 531 | + */ | ||
| 532 | + TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder(); | ||
| 533 | + sbuilder.matchVlanId(vlanId); | ||
| 534 | + sbuilder.matchEthDst(MacAddress.NONE); | ||
| 535 | + | ||
| 536 | + ForwardingObjective.Builder fob = DefaultForwardingObjective.builder(); | ||
| 537 | + fob.withFlag(Flag.SPECIFIC) | ||
| 538 | + .withSelector(sbuilder.build()) | ||
| 539 | + .nextStep(nextId) | ||
| 540 | + .withPriority(5) | ||
| 541 | + .fromApp(srManager.appId) | ||
| 542 | + .makePermanent(); | ||
| 543 | + | ||
| 544 | + srManager.flowObjectiveService.forward( | ||
| 545 | + deviceId, | ||
| 546 | + fob.add(new SRObjectiveContext( | ||
| 547 | + deviceId, | ||
| 548 | + SRObjectiveContext.ObjectiveType.FORWARDING) | ||
| 549 | + ) | ||
| 550 | + ); | ||
| 551 | + }); | ||
| 552 | + } | ||
| 553 | + | ||
| 554 | + | ||
| 492 | private PortNumber selectOnePort(DeviceId srcId, Set<DeviceId> destIds) { | 555 | private PortNumber selectOnePort(DeviceId srcId, Set<DeviceId> destIds) { |
| 493 | 556 | ||
| 494 | Set<Link> links = srManager.linkService.getDeviceLinks(srcId); | 557 | Set<Link> links = srManager.linkService.getDeviceLinks(srcId); | ... | ... |
This diff is collapsed. Click to expand it.
| ... | @@ -224,8 +224,8 @@ public class DefaultGroupHandler { | ... | @@ -224,8 +224,8 @@ public class DefaultGroupHandler { |
| 224 | .setEthSrc(nodeMacAddr); | 224 | .setEthSrc(nodeMacAddr); |
| 225 | if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) { | 225 | if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) { |
| 226 | tBuilder.pushMpls() | 226 | tBuilder.pushMpls() |
| 227 | - .setMpls(MplsLabel. | 227 | + .copyTtlOut() |
| 228 | - mplsLabel(ns.getEdgeLabel())); | 228 | + .setMpls(MplsLabel.mplsLabel(ns.getEdgeLabel())); |
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | Integer nextId = nsNextObjStore. | 231 | Integer nextId = nsNextObjStore. |
| ... | @@ -292,8 +292,9 @@ public class DefaultGroupHandler { | ... | @@ -292,8 +292,9 @@ public class DefaultGroupHandler { |
| 292 | .setEthDst(dstMac) | 292 | .setEthDst(dstMac) |
| 293 | .setEthSrc(nodeMacAddr); | 293 | .setEthSrc(nodeMacAddr); |
| 294 | if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) { | 294 | if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) { |
| 295 | - tBuilder.pushMpls().setMpls(MplsLabel.mplsLabel(ns | 295 | + tBuilder.pushMpls() |
| 296 | - .getEdgeLabel())); | 296 | + .copyTtlOut() |
| 297 | + .setMpls(MplsLabel.mplsLabel(ns.getEdgeLabel())); | ||
| 297 | } | 298 | } |
| 298 | 299 | ||
| 299 | Integer nextId = nsNextObjStore. | 300 | Integer nextId = nsNextObjStore. |
| ... | @@ -536,8 +537,9 @@ public class DefaultGroupHandler { | ... | @@ -536,8 +537,9 @@ public class DefaultGroupHandler { |
| 536 | .setEthDst(deviceMac) | 537 | .setEthDst(deviceMac) |
| 537 | .setEthSrc(nodeMacAddr); | 538 | .setEthSrc(nodeMacAddr); |
| 538 | if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) { | 539 | if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) { |
| 539 | - tBuilder.pushMpls().setMpls(MplsLabel.mplsLabel(ns | 540 | + tBuilder.pushMpls() |
| 540 | - .getEdgeLabel())); | 541 | + .copyTtlOut() |
| 542 | + .setMpls(MplsLabel.mplsLabel(ns.getEdgeLabel())); | ||
| 541 | } | 543 | } |
| 542 | nextObjBuilder.addTreatment(tBuilder.build()); | 544 | nextObjBuilder.addTreatment(tBuilder.build()); |
| 543 | } | 545 | } | ... | ... |
This diff is collapsed. Click to expand it.
| ... | @@ -21,6 +21,7 @@ import java.util.List; | ... | @@ -21,6 +21,7 @@ import java.util.List; |
| 21 | 21 | ||
| 22 | import org.onlab.packet.Ethernet; | 22 | import org.onlab.packet.Ethernet; |
| 23 | import org.onlab.packet.MacAddress; | 23 | import org.onlab.packet.MacAddress; |
| 24 | +import org.onlab.packet.VlanId; | ||
| 24 | import org.onosproject.core.ApplicationId; | 25 | import org.onosproject.core.ApplicationId; |
| 25 | import org.onosproject.net.behaviour.NextGroup; | 26 | import org.onosproject.net.behaviour.NextGroup; |
| 26 | import org.onosproject.net.flow.DefaultFlowRule; | 27 | import org.onosproject.net.flow.DefaultFlowRule; |
| ... | @@ -34,6 +35,7 @@ import org.onosproject.net.flow.criteria.EthCriterion; | ... | @@ -34,6 +35,7 @@ import org.onosproject.net.flow.criteria.EthCriterion; |
| 34 | import org.onosproject.net.flow.criteria.EthTypeCriterion; | 35 | import org.onosproject.net.flow.criteria.EthTypeCriterion; |
| 35 | import org.onosproject.net.flow.criteria.IPCriterion; | 36 | import org.onosproject.net.flow.criteria.IPCriterion; |
| 36 | import org.onosproject.net.flow.criteria.MplsCriterion; | 37 | import org.onosproject.net.flow.criteria.MplsCriterion; |
| 38 | +import org.onosproject.net.flow.criteria.VlanIdCriterion; | ||
| 37 | import org.onosproject.net.flow.instructions.Instruction; | 39 | import org.onosproject.net.flow.instructions.Instruction; |
| 38 | import org.onosproject.net.flowobjective.FilteringObjective; | 40 | import org.onosproject.net.flowobjective.FilteringObjective; |
| 39 | import org.onosproject.net.flowobjective.ForwardingObjective; | 41 | import org.onosproject.net.flowobjective.ForwardingObjective; |
| ... | @@ -175,12 +177,13 @@ public class SpringOpenTTPDell extends SpringOpenTTP { | ... | @@ -175,12 +177,13 @@ public class SpringOpenTTPDell extends SpringOpenTTP { |
| 175 | //Dell switches need ETH_DST based match condition in all IP table entries. | 177 | //Dell switches need ETH_DST based match condition in all IP table entries. |
| 176 | //So while processing the ETH_DST based filtering objective, store | 178 | //So while processing the ETH_DST based filtering objective, store |
| 177 | //the device MAC to be used locally to use it while pushing the IP rules. | 179 | //the device MAC to be used locally to use it while pushing the IP rules. |
| 178 | - protected List<FlowRule> processEthDstFilter(Criterion c, | 180 | + protected List<FlowRule> processEthDstFilter(EthCriterion ethCriterion, |
| 181 | + VlanIdCriterion vlanIdCriterion, | ||
| 179 | FilteringObjective filt, | 182 | FilteringObjective filt, |
| 183 | + VlanId assignedVlan, | ||
| 180 | ApplicationId applicationId) { | 184 | ApplicationId applicationId) { |
| 181 | // Store device termination Mac to be used in IP flow entries | 185 | // Store device termination Mac to be used in IP flow entries |
| 182 | - EthCriterion e = (EthCriterion) c; | 186 | + deviceTMac = ethCriterion.mac(); |
| 183 | - deviceTMac = e.mac(); | ||
| 184 | 187 | ||
| 185 | log.debug("For now not adding any TMAC rules " | 188 | log.debug("For now not adding any TMAC rules " |
| 186 | + "into Dell switches as it is ignoring"); | 189 | + "into Dell switches as it is ignoring"); |
| ... | @@ -189,8 +192,9 @@ public class SpringOpenTTPDell extends SpringOpenTTP { | ... | @@ -189,8 +192,9 @@ public class SpringOpenTTPDell extends SpringOpenTTP { |
| 189 | } | 192 | } |
| 190 | 193 | ||
| 191 | @Override | 194 | @Override |
| 192 | - protected List<FlowRule> processVlanIdFilter(Criterion c, | 195 | + protected List<FlowRule> processVlanIdFilter(VlanIdCriterion vlanIdCriterion, |
| 193 | FilteringObjective filt, | 196 | FilteringObjective filt, |
| 197 | + VlanId assignedVlan, | ||
| 194 | ApplicationId applicationId) { | 198 | ApplicationId applicationId) { |
| 195 | log.debug("For now not adding any VLAN rules " | 199 | log.debug("For now not adding any VLAN rules " |
| 196 | + "into Dell switches as it is ignoring"); | 200 | + "into Dell switches as it is ignoring"); | ... | ... |
-
Please register or login to post a comment