Charles Chan
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
...@@ -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);
......
...@@ -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 }
......
...@@ -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");
......