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 | + |
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 | + }); | ||
223 | } | 258 | } |
224 | - } | 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