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 +
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);
......
...@@ -22,6 +22,7 @@ import org.apache.felix.scr.annotations.Reference; ...@@ -22,6 +22,7 @@ import org.apache.felix.scr.annotations.Reference;
22 import org.apache.felix.scr.annotations.ReferenceCardinality; 22 import org.apache.felix.scr.annotations.ReferenceCardinality;
23 import org.apache.felix.scr.annotations.Service; 23 import org.apache.felix.scr.annotations.Service;
24 import org.onlab.packet.Ethernet; 24 import org.onlab.packet.Ethernet;
25 +import org.onlab.packet.MacAddress;
25 import org.onlab.packet.VlanId; 26 import org.onlab.packet.VlanId;
26 import org.onlab.packet.IPv4; 27 import org.onlab.packet.IPv4;
27 import org.onlab.packet.Ip4Address; 28 import org.onlab.packet.Ip4Address;
...@@ -33,11 +34,23 @@ import org.onosproject.core.ApplicationId; ...@@ -33,11 +34,23 @@ import org.onosproject.core.ApplicationId;
33 import org.onosproject.core.CoreService; 34 import org.onosproject.core.CoreService;
34 import org.onosproject.event.Event; 35 import org.onosproject.event.Event;
35 import org.onosproject.net.ConnectPoint; 36 import org.onosproject.net.ConnectPoint;
37 +import org.onosproject.net.PortNumber;
36 import org.onosproject.net.config.ConfigFactory; 38 import org.onosproject.net.config.ConfigFactory;
37 import org.onosproject.net.config.NetworkConfigEvent; 39 import org.onosproject.net.config.NetworkConfigEvent;
38 import org.onosproject.net.config.NetworkConfigRegistry; 40 import org.onosproject.net.config.NetworkConfigRegistry;
39 import org.onosproject.net.config.NetworkConfigListener; 41 import org.onosproject.net.config.NetworkConfigListener;
40 import org.onosproject.net.config.basics.SubjectFactories; 42 import org.onosproject.net.config.basics.SubjectFactories;
43 +import org.onosproject.net.flow.DefaultTrafficSelector;
44 +import org.onosproject.net.flow.DefaultTrafficTreatment;
45 +import org.onosproject.net.flow.TrafficSelector;
46 +import org.onosproject.net.flow.TrafficTreatment;
47 +import org.onosproject.net.flowobjective.DefaultForwardingObjective;
48 +import org.onosproject.net.flowobjective.ForwardingObjective;
49 +import org.onosproject.net.flowobjective.Objective;
50 +import org.onosproject.net.flowobjective.ObjectiveContext;
51 +import org.onosproject.net.flowobjective.ObjectiveError;
52 +import org.onosproject.net.host.HostEvent;
53 +import org.onosproject.net.host.HostListener;
41 import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException; 54 import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
42 import org.onosproject.segmentrouting.config.DeviceConfiguration; 55 import org.onosproject.segmentrouting.config.DeviceConfiguration;
43 import org.onosproject.segmentrouting.config.SegmentRoutingConfig; 56 import org.onosproject.segmentrouting.config.SegmentRoutingConfig;
...@@ -139,11 +152,13 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -139,11 +152,13 @@ public class SegmentRoutingManager implements SegmentRoutingService {
139 152
140 private static ScheduledFuture<?> eventHandlerFuture = null; 153 private static ScheduledFuture<?> eventHandlerFuture = null;
141 private ConcurrentLinkedQueue<Event> eventQueue = new ConcurrentLinkedQueue<Event>(); 154 private ConcurrentLinkedQueue<Event> eventQueue = new ConcurrentLinkedQueue<Event>();
142 - private Map<DeviceId, DefaultGroupHandler> groupHandlerMap = new ConcurrentHashMap<DeviceId, DefaultGroupHandler>(); 155 + private Map<DeviceId, DefaultGroupHandler> groupHandlerMap =
156 + new ConcurrentHashMap<DeviceId, DefaultGroupHandler>();
143 // Per device next objective ID store with (device id + neighbor set) as key 157 // Per device next objective ID store with (device id + neighbor set) as key
144 - private EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey, 158 + private EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey, Integer>
145 - Integer> nsNextObjStore = null; 159 + nsNextObjStore = null;
146 - private EventuallyConsistentMap<SubnetNextObjectiveStoreKey, Integer> subnetNextObjStore = null; 160 + private EventuallyConsistentMap<SubnetNextObjectiveStoreKey, Integer>
161 + subnetNextObjStore = null;
147 private EventuallyConsistentMap<String, Tunnel> tunnelStore = null; 162 private EventuallyConsistentMap<String, Tunnel> tunnelStore = null;
148 private EventuallyConsistentMap<String, Policy> policyStore = null; 163 private EventuallyConsistentMap<String, Policy> policyStore = null;
149 // Per device, per-subnet assigned-vlans store, with (device id + subnet 164 // Per device, per-subnet assigned-vlans store, with (device id + subnet
...@@ -170,6 +185,8 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -170,6 +185,8 @@ public class SegmentRoutingManager implements SegmentRoutingService {
170 } 185 }
171 }; 186 };
172 187
188 + private final HostListener hostListener = new InternalHostListener();
189 +
173 private Object threadSchedulerLock = new Object(); 190 private Object threadSchedulerLock = new Object();
174 private static int numOfEventsQueued = 0; 191 private static int numOfEventsQueued = 0;
175 private static int numOfEventsExecuted = 0; 192 private static int numOfEventsExecuted = 0;
...@@ -259,6 +276,8 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -259,6 +276,8 @@ public class SegmentRoutingManager implements SegmentRoutingService {
259 cfgService.addListener(cfgListener); 276 cfgService.addListener(cfgListener);
260 cfgService.registerConfigFactory(cfgFactory); 277 cfgService.registerConfigFactory(cfgFactory);
261 278
279 + hostService.addListener(hostListener);
280 +
262 processor = new InternalPacketProcessor(); 281 processor = new InternalPacketProcessor();
263 linkListener = new InternalLinkListener(); 282 linkListener = new InternalLinkListener();
264 deviceListener = new InternalDeviceListener(); 283 deviceListener = new InternalDeviceListener();
...@@ -637,6 +656,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -637,6 +656,7 @@ public class SegmentRoutingManager implements SegmentRoutingService {
637 if (mastershipService.isLocalMaster(device.id())) { 656 if (mastershipService.isLocalMaster(device.id())) {
638 DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id()); 657 DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
639 groupHandler.createGroupsFromSubnetConfig(); 658 groupHandler.createGroupsFromSubnetConfig();
659 + routingRulePopulator.populateSubnetBroadcastRule(device.id());
640 } 660 }
641 } 661 }
642 662
...@@ -703,6 +723,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -703,6 +723,7 @@ public class SegmentRoutingManager implements SegmentRoutingService {
703 if (mastershipService.isLocalMaster(device.id())) { 723 if (mastershipService.isLocalMaster(device.id())) {
704 DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id()); 724 DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
705 groupHandler.createGroupsFromSubnetConfig(); 725 groupHandler.createGroupsFromSubnetConfig();
726 + routingRulePopulator.populateSubnetBroadcastRule(device.id());
706 } 727 }
707 } 728 }
708 729
...@@ -723,4 +744,205 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -723,4 +744,205 @@ public class SegmentRoutingManager implements SegmentRoutingService {
723 } 744 }
724 } 745 }
725 } 746 }
747 +
748 + private class InternalHostListener implements HostListener {
749 + private ForwardingObjective.Builder getForwardingObjectiveBuilder(
750 + MacAddress mac, VlanId vlanId, PortNumber port) {
751 + TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
752 + sbuilder.matchEthDst(mac);
753 + sbuilder.matchVlanId(vlanId);
754 +
755 + TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
756 + // TODO Move popVlan from flow action to group action
757 + tbuilder.immediate().popVlan();
758 + tbuilder.immediate().setOutput(port);
759 +
760 + return DefaultForwardingObjective.builder()
761 + .withFlag(ForwardingObjective.Flag.SPECIFIC)
762 + .withSelector(sbuilder.build())
763 + .withTreatment(tbuilder.build())
764 + .withPriority(100)
765 + .fromApp(appId)
766 + .makePermanent();
767 + }
768 +
769 + private void processHostAddedEvent(HostEvent event) {
770 + MacAddress mac = event.subject().mac();
771 + VlanId vlanId = event.subject().vlan();
772 + DeviceId deviceId = event.subject().location().deviceId();
773 + PortNumber port = event.subject().location().port();
774 + Set<IpAddress> ips = event.subject().ipAddresses();
775 + log.debug("Host {}/{} is added at {}:{}", mac, vlanId, deviceId, port);
776 +
777 + // TODO Move bridging table population to a separate class
778 + // Populate bridging table entry
779 + ForwardingObjective.Builder fob =
780 + getForwardingObjectiveBuilder(mac, vlanId, port);
781 + flowObjectiveService.forward(deviceId, fob.add(
782 + new BridgingTableObjectiveContext(mac, vlanId)
783 + ));
784 +
785 + // Populate IP table entry
786 + ips.forEach(ip -> {
787 + if (ip.isIp4()) {
788 + routingRulePopulator.populateIpRuleForHost(
789 + deviceId, ip.getIp4Address(), mac, port);
790 + }
791 + });
792 + }
793 +
794 + private void processHostRemoveEvent(HostEvent event) {
795 + MacAddress mac = event.subject().mac();
796 + VlanId vlanId = event.subject().vlan();
797 + DeviceId deviceId = event.subject().location().deviceId();
798 + PortNumber port = event.subject().location().port();
799 + Set<IpAddress> ips = event.subject().ipAddresses();
800 + log.debug("Host {}/{} is removed from {}:{}", mac, vlanId, deviceId, port);
801 +
802 + // Revoke bridging table entry
803 + ForwardingObjective.Builder fob =
804 + getForwardingObjectiveBuilder(mac, vlanId, port);
805 + flowObjectiveService.forward(deviceId, fob.remove(
806 + new BridgingTableObjectiveContext(mac, vlanId)
807 + ));
808 +
809 + // Revoke IP table entry
810 + ips.forEach(ip -> {
811 + if (ip.isIp4()) {
812 + routingRulePopulator.revokeIpRuleForHost(
813 + deviceId, ip.getIp4Address(), mac, port);
814 + }
815 + });
816 + }
817 +
818 + private void processHostMovedEvent(HostEvent event) {
819 + MacAddress mac = event.subject().mac();
820 + VlanId vlanId = event.subject().vlan();
821 + DeviceId prevDeviceId = event.prevSubject().location().deviceId();
822 + PortNumber prevPort = event.prevSubject().location().port();
823 + Set<IpAddress> prevIps = event.prevSubject().ipAddresses();
824 + DeviceId newDeviceId = event.subject().location().deviceId();
825 + PortNumber newPort = event.subject().location().port();
826 + Set<IpAddress> newIps = event.subject().ipAddresses();
827 + log.debug("Host {}/{} is moved from {}:{} to {}:{}",
828 + mac, vlanId, prevDeviceId, prevPort, newDeviceId, newPort);
829 +
830 + // Revoke previous bridging table entry
831 + ForwardingObjective.Builder prevFob =
832 + getForwardingObjectiveBuilder(mac, vlanId, prevPort);
833 + flowObjectiveService.forward(prevDeviceId, prevFob.remove(
834 + new BridgingTableObjectiveContext(mac, vlanId)
835 + ));
836 +
837 + // Revoke previous IP table entry
838 + prevIps.forEach(ip -> {
839 + if (ip.isIp4()) {
840 + routingRulePopulator.revokeIpRuleForHost(
841 + prevDeviceId, ip.getIp4Address(), mac, prevPort);
842 + }
843 + });
844 +
845 + // Populate new bridging table entry
846 + ForwardingObjective.Builder newFob =
847 + getForwardingObjectiveBuilder(mac, vlanId, prevPort);
848 + flowObjectiveService.forward(newDeviceId, newFob.add(
849 + new BridgingTableObjectiveContext(mac, vlanId)
850 + ));
851 +
852 + // Populate new IP table entry
853 + newIps.forEach(ip -> {
854 + if (ip.isIp4()) {
855 + routingRulePopulator.populateIpRuleForHost(
856 + newDeviceId, ip.getIp4Address(), mac, newPort);
857 + }
858 + });
859 + }
860 +
861 + private void processHostUpdatedEvent(HostEvent event) {
862 + MacAddress mac = event.subject().mac();
863 + VlanId vlanId = event.subject().vlan();
864 + DeviceId prevDeviceId = event.prevSubject().location().deviceId();
865 + PortNumber prevPort = event.prevSubject().location().port();
866 + Set<IpAddress> prevIps = event.prevSubject().ipAddresses();
867 + DeviceId newDeviceId = event.subject().location().deviceId();
868 + PortNumber newPort = event.subject().location().port();
869 + Set<IpAddress> newIps = event.subject().ipAddresses();
870 + log.debug("Host {}/{} is updated", mac, vlanId);
871 +
872 + // Revoke previous IP table entry
873 + prevIps.forEach(ip -> {
874 + if (ip.isIp4()) {
875 + routingRulePopulator.revokeIpRuleForHost(
876 + prevDeviceId, ip.getIp4Address(), mac, prevPort);
877 + }
878 + });
879 +
880 + // Populate new IP table entry
881 + newIps.forEach(ip -> {
882 + if (ip.isIp4()) {
883 + routingRulePopulator.populateIpRuleForHost(
884 + newDeviceId, ip.getIp4Address(), mac, newPort);
885 + }
886 + });
887 + }
888 +
889 + @Override
890 + public void event(HostEvent event) {
891 + // Do not proceed without mastership
892 + DeviceId deviceId = event.subject().location().deviceId();
893 + if (!mastershipService.isLocalMaster(deviceId)) {
894 + return;
895 + }
896 +
897 + switch (event.type()) {
898 + case HOST_ADDED:
899 + processHostAddedEvent(event);
900 + break;
901 + case HOST_MOVED:
902 + processHostMovedEvent(event);
903 + break;
904 + case HOST_REMOVED:
905 + processHostRemoveEvent(event);
906 + break;
907 + case HOST_UPDATED:
908 + processHostUpdatedEvent(event);
909 + break;
910 + default:
911 + log.warn("Unsupported host event type: {}", event.type());
912 + break;
913 + }
914 + }
915 + }
916 +
917 + private static class BridgingTableObjectiveContext implements ObjectiveContext {
918 + final MacAddress mac;
919 + final VlanId vlanId;
920 +
921 + BridgingTableObjectiveContext(MacAddress mac, VlanId vlanId) {
922 + this.mac = mac;
923 + this.vlanId = vlanId;
924 + }
925 +
926 + @Override
927 + public void onSuccess(Objective objective) {
928 + if (objective.op() == Objective.Operation.ADD) {
929 + log.debug("Successfully populate bridging table entry for {}/{}",
930 + mac, vlanId);
931 + } else {
932 + log.debug("Successfully revoke bridging table entry for {}/{}",
933 + mac, vlanId);
934 + }
935 + }
936 +
937 + @Override
938 + public void onError(Objective objective, ObjectiveError error) {
939 + if (objective.op() == Objective.Operation.ADD) {
940 + log.debug("Fail to populate bridging table entry for {}/{}. {}",
941 + mac, vlanId, error);
942 + } else {
943 + log.debug("Fail to revoke bridging table entry for {}/{}. {}",
944 + mac, vlanId, error);
945 + }
946 + }
947 + }
726 } 948 }
......
...@@ -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 }
......
...@@ -25,6 +25,7 @@ import com.google.common.cache.RemovalNotification; ...@@ -25,6 +25,7 @@ import com.google.common.cache.RemovalNotification;
25 25
26 import org.onlab.osgi.ServiceDirectory; 26 import org.onlab.osgi.ServiceDirectory;
27 import org.onlab.packet.Ethernet; 27 import org.onlab.packet.Ethernet;
28 +import org.onlab.packet.MacAddress;
28 import org.onlab.packet.VlanId; 29 import org.onlab.packet.VlanId;
29 import org.onlab.util.KryoNamespace; 30 import org.onlab.util.KryoNamespace;
30 import org.onosproject.core.ApplicationId; 31 import org.onosproject.core.ApplicationId;
...@@ -54,6 +55,7 @@ import org.onosproject.net.flow.criteria.PortCriterion; ...@@ -54,6 +55,7 @@ import org.onosproject.net.flow.criteria.PortCriterion;
54 import org.onosproject.net.flow.criteria.VlanIdCriterion; 55 import org.onosproject.net.flow.criteria.VlanIdCriterion;
55 import org.onosproject.net.flow.instructions.Instruction; 56 import org.onosproject.net.flow.instructions.Instruction;
56 import org.onosproject.net.flow.instructions.Instructions.OutputInstruction; 57 import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
58 +import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
57 import org.onosproject.net.flowobjective.FilteringObjective; 59 import org.onosproject.net.flowobjective.FilteringObjective;
58 import org.onosproject.net.flowobjective.FlowObjectiveStore; 60 import org.onosproject.net.flowobjective.FlowObjectiveStore;
59 import org.onosproject.net.flowobjective.ForwardingObjective; 61 import org.onosproject.net.flowobjective.ForwardingObjective;
...@@ -94,7 +96,9 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -94,7 +96,9 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
94 private static final int TABLE_TMAC = 1; 96 private static final int TABLE_TMAC = 1;
95 private static final int TABLE_IPV4_UNICAST = 2; 97 private static final int TABLE_IPV4_UNICAST = 2;
96 private static final int TABLE_MPLS = 3; 98 private static final int TABLE_MPLS = 3;
99 + private static final int TABLE_DMAC = 4;
97 private static final int TABLE_ACL = 5; 100 private static final int TABLE_ACL = 5;
101 + private static final int TABLE_SMAC = 6;
98 102
99 /** 103 /**
100 * Set the default values. These variables will get overwritten based on the 104 * Set the default values. These variables will get overwritten based on the
...@@ -104,7 +108,9 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -104,7 +108,9 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
104 protected int tmacTableId = TABLE_TMAC; 108 protected int tmacTableId = TABLE_TMAC;
105 protected int ipv4UnicastTableId = TABLE_IPV4_UNICAST; 109 protected int ipv4UnicastTableId = TABLE_IPV4_UNICAST;
106 protected int mplsTableId = TABLE_MPLS; 110 protected int mplsTableId = TABLE_MPLS;
111 + protected int dstMacTableId = TABLE_DMAC;
107 protected int aclTableId = TABLE_ACL; 112 protected int aclTableId = TABLE_ACL;
113 + protected int srcMacTableId = TABLE_SMAC;
108 114
109 protected final Logger log = getLogger(getClass()); 115 protected final Logger log = getLogger(getClass());
110 116
...@@ -448,12 +454,14 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -448,12 +454,14 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
448 fwd.treatment().allInstructions().get(0).type() == Instruction.Type.OUTPUT) { 454 fwd.treatment().allInstructions().get(0).type() == Instruction.Type.OUTPUT) {
449 OutputInstruction o = (OutputInstruction) fwd.treatment().allInstructions().get(0); 455 OutputInstruction o = (OutputInstruction) fwd.treatment().allInstructions().get(0);
450 if (o.port() == PortNumber.CONTROLLER) { 456 if (o.port() == PortNumber.CONTROLLER) {
451 - log.warn("Punts to the controller are handled by misses in" 457 + treatmentBuilder.punt();
452 - + " the TMAC, IP and MPLS tables."); 458 + treatment = treatmentBuilder.build();
453 - return Collections.emptySet(); 459 + } else {
454 - } 460 + treatment = fwd.treatment();
455 } 461 }
462 + } else {
456 treatment = fwd.treatment(); 463 treatment = fwd.treatment();
464 + }
457 } else { 465 } else {
458 log.warn("VERSATILE forwarding objective needs next objective ID " 466 log.warn("VERSATILE forwarding objective needs next objective ID "
459 + "or treatment."); 467 + "or treatment.");
...@@ -475,19 +483,52 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -475,19 +483,52 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
475 return Collections.singletonList(ruleBuilder.build()); 483 return Collections.singletonList(ruleBuilder.build());
476 } 484 }
477 485
478 - protected Collection<FlowRule> processSpecific(ForwardingObjective fwd) { 486 + private boolean isSupportedEthTypeObjective(ForwardingObjective fwd) {
479 - log.debug("Processing specific");
480 TrafficSelector selector = fwd.selector(); 487 TrafficSelector selector = fwd.selector();
481 EthTypeCriterion ethType = (EthTypeCriterion) selector 488 EthTypeCriterion ethType = (EthTypeCriterion) selector
482 .getCriterion(Criterion.Type.ETH_TYPE); 489 .getCriterion(Criterion.Type.ETH_TYPE);
483 if ((ethType == null) || 490 if ((ethType == null) ||
484 - (ethType.ethType().toShort() != Ethernet.TYPE_IPV4) && 491 + ((ethType.ethType().toShort() != Ethernet.TYPE_IPV4) &&
485 - (ethType.ethType().toShort() != Ethernet.MPLS_UNICAST)) { 492 + (ethType.ethType().toShort() != Ethernet.MPLS_UNICAST))) {
493 + return false;
494 + }
495 + return true;
496 + }
497 +
498 + private boolean isSupportedEthDstObjective(ForwardingObjective fwd) {
499 + TrafficSelector selector = fwd.selector();
500 + EthCriterion ethDst = (EthCriterion) selector
501 + .getCriterion(Criterion.Type.ETH_DST);
502 + VlanIdCriterion vlanId = (VlanIdCriterion) selector
503 + .getCriterion(Criterion.Type.VLAN_VID);
504 + if (ethDst == null && vlanId == null) {
505 + return false;
506 + }
507 + return true;
508 + }
509 +
510 + protected Collection<FlowRule> processSpecific(ForwardingObjective fwd) {
511 + log.debug("Processing specific");
512 + boolean isEthTypeObj = isSupportedEthTypeObjective(fwd);
513 + boolean isEthDstObj = isSupportedEthDstObjective(fwd);
514 +
515 + if (isEthTypeObj) {
516 + return processEthTypeSpecificObjective(fwd);
517 + } else if (isEthDstObj) {
518 + return processEthDstSpecificObjective(fwd);
519 + } else {
486 log.warn("processSpecific: Unsupported " 520 log.warn("processSpecific: Unsupported "
487 + "forwarding objective criteraia"); 521 + "forwarding objective criteraia");
488 fail(fwd, ObjectiveError.UNSUPPORTED); 522 fail(fwd, ObjectiveError.UNSUPPORTED);
489 return Collections.emptySet(); 523 return Collections.emptySet();
490 } 524 }
525 + }
526 +
527 + protected Collection<FlowRule>
528 + processEthTypeSpecificObjective(ForwardingObjective fwd) {
529 + TrafficSelector selector = fwd.selector();
530 + EthTypeCriterion ethType = (EthTypeCriterion) selector
531 + .getCriterion(Criterion.Type.ETH_TYPE);
491 532
492 TrafficSelector.Builder filteredSelectorBuilder = 533 TrafficSelector.Builder filteredSelectorBuilder =
493 DefaultTrafficSelector.builder(); 534 DefaultTrafficSelector.builder();
...@@ -565,59 +606,167 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -565,59 +606,167 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
565 606
566 } 607 }
567 608
568 - protected List<FlowRule> processEthDstFilter(Criterion c, 609 + protected Collection<FlowRule>
610 + processEthDstSpecificObjective(ForwardingObjective fwd) {
611 + List<FlowRule> rules = new ArrayList<>();
612 +
613 + // Build filtered selector
614 + TrafficSelector selector = fwd.selector();
615 + EthCriterion ethCriterion = (EthCriterion) selector
616 + .getCriterion(Criterion.Type.ETH_DST);
617 + VlanIdCriterion vlanIdCriterion = (VlanIdCriterion) selector
618 + .getCriterion(Criterion.Type.VLAN_VID);
619 + TrafficSelector.Builder filteredSelectorBuilder =
620 + DefaultTrafficSelector.builder();
621 + // Do not match MacAddress for subnet broadcast entry
622 + if (!ethCriterion.mac().equals(MacAddress.NONE)) {
623 + filteredSelectorBuilder.matchEthDst(ethCriterion.mac());
624 + }
625 + filteredSelectorBuilder.matchVlanId(vlanIdCriterion.vlanId());
626 + TrafficSelector filteredSelector = filteredSelectorBuilder.build();
627 +
628 + // Build filtered treatment
629 + TrafficTreatment.Builder treatmentBuilder =
630 + DefaultTrafficTreatment.builder();
631 + if (fwd.treatment() != null) {
632 + treatmentBuilder.deferred();
633 + fwd.treatment().allInstructions().forEach(treatmentBuilder::add);
634 + }
635 + if (fwd.nextId() != null) {
636 + NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId());
637 + if (next != null) {
638 + GroupKey key = appKryo.deserialize(next.data());
639 + Group group = groupService.getGroup(deviceId, key);
640 + if (group != null) {
641 + treatmentBuilder.deferred().group(group.id());
642 + } else {
643 + log.warn("Group Missing");
644 + fail(fwd, ObjectiveError.GROUPMISSING);
645 + return Collections.emptySet();
646 + }
647 + }
648 + }
649 + treatmentBuilder.immediate().transition(aclTableId);
650 + TrafficTreatment filteredTreatment = treatmentBuilder.build();
651 +
652 + // Build bridging table entries
653 + FlowRule.Builder flowRuleBuilder = DefaultFlowRule.builder();
654 + flowRuleBuilder.fromApp(fwd.appId())
655 + .withPriority(fwd.priority())
656 + .forDevice(deviceId)
657 + .withSelector(filteredSelector)
658 + .withTreatment(filteredTreatment)
659 + .forTable(dstMacTableId);
660 + if (fwd.permanent()) {
661 + flowRuleBuilder.makePermanent();
662 + } else {
663 + flowRuleBuilder.makeTemporary(fwd.timeout());
664 + }
665 + rules.add(flowRuleBuilder.build());
666 +
667 + /*
668 + // TODO Emulate source MAC table behavior
669 + // Do not install source MAC table entry for subnet broadcast
670 + if (!ethCriterion.mac().equals(MacAddress.NONE)) {
671 + // Build filtered selector
672 + selector = fwd.selector();
673 + ethCriterion = (EthCriterion) selector.getCriterion(Criterion.Type.ETH_DST);
674 + filteredSelectorBuilder = DefaultTrafficSelector.builder();
675 + filteredSelectorBuilder.matchEthSrc(ethCriterion.mac());
676 + filteredSelector = filteredSelectorBuilder.build();
677 +
678 + // Build empty treatment. Apply existing instruction if match.
679 + treatmentBuilder = DefaultTrafficTreatment.builder();
680 + filteredTreatment = treatmentBuilder.build();
681 +
682 + // Build bridging table entries
683 + flowRuleBuilder = DefaultFlowRule.builder();
684 + flowRuleBuilder.fromApp(fwd.appId())
685 + .withPriority(fwd.priority())
686 + .forDevice(deviceId)
687 + .withSelector(filteredSelector)
688 + .withTreatment(filteredTreatment)
689 + .forTable(srcMacTableId)
690 + .makePermanent();
691 + rules.add(flowRuleBuilder.build());
692 + }
693 + */
694 +
695 + return rules;
696 + }
697 +
698 + protected List<FlowRule> processEthDstFilter(EthCriterion ethCriterion,
699 + VlanIdCriterion vlanIdCriterion,
569 FilteringObjective filt, 700 FilteringObjective filt,
701 + VlanId assignedVlan,
570 ApplicationId applicationId) { 702 ApplicationId applicationId) {
703 + //handling untagged packets via assigned VLAN
704 + if (vlanIdCriterion.vlanId() == VlanId.NONE) {
705 + vlanIdCriterion = (VlanIdCriterion) Criteria.matchVlanId(assignedVlan);
706 + }
707 +
708 + /*
709 + * Note: CpqD switches do not handle MPLS-related operation properly
710 + * for a packet with VLAN tag. We pop VLAN here as a workaround.
711 + * Side effect: HostService learns redundant hosts with same MAC but
712 + * different VLAN. No known side effect on the network reachability.
713 + */
571 List<FlowRule> rules = new ArrayList<>(); 714 List<FlowRule> rules = new ArrayList<>();
572 - EthCriterion e = (EthCriterion) c;
573 TrafficSelector.Builder selectorIp = DefaultTrafficSelector 715 TrafficSelector.Builder selectorIp = DefaultTrafficSelector
574 .builder(); 716 .builder();
575 TrafficTreatment.Builder treatmentIp = DefaultTrafficTreatment 717 TrafficTreatment.Builder treatmentIp = DefaultTrafficTreatment
576 .builder(); 718 .builder();
577 - selectorIp.matchEthDst(e.mac()); 719 + selectorIp.matchEthDst(ethCriterion.mac());
578 selectorIp.matchEthType(Ethernet.TYPE_IPV4); 720 selectorIp.matchEthType(Ethernet.TYPE_IPV4);
721 + selectorIp.matchVlanId(vlanIdCriterion.vlanId());
722 + treatmentIp.popVlan();
579 treatmentIp.transition(ipv4UnicastTableId); 723 treatmentIp.transition(ipv4UnicastTableId);
580 FlowRule ruleIp = DefaultFlowRule.builder().forDevice(deviceId) 724 FlowRule ruleIp = DefaultFlowRule.builder().forDevice(deviceId)
581 .withSelector(selectorIp.build()) 725 .withSelector(selectorIp.build())
582 .withTreatment(treatmentIp.build()) 726 .withTreatment(treatmentIp.build())
583 .withPriority(filt.priority()).fromApp(applicationId) 727 .withPriority(filt.priority()).fromApp(applicationId)
584 .makePermanent().forTable(tmacTableId).build(); 728 .makePermanent().forTable(tmacTableId).build();
585 - log.debug("adding IP ETH rule for MAC: {}", e.mac()); 729 + log.debug("adding IP ETH rule for MAC: {}", ethCriterion.mac());
586 rules.add(ruleIp); 730 rules.add(ruleIp);
587 731
588 TrafficSelector.Builder selectorMpls = DefaultTrafficSelector 732 TrafficSelector.Builder selectorMpls = DefaultTrafficSelector
589 .builder(); 733 .builder();
590 TrafficTreatment.Builder treatmentMpls = DefaultTrafficTreatment 734 TrafficTreatment.Builder treatmentMpls = DefaultTrafficTreatment
591 .builder(); 735 .builder();
592 - selectorMpls.matchEthDst(e.mac()); 736 + selectorMpls.matchEthDst(ethCriterion.mac());
593 selectorMpls.matchEthType(Ethernet.MPLS_UNICAST); 737 selectorMpls.matchEthType(Ethernet.MPLS_UNICAST);
738 + selectorMpls.matchVlanId(vlanIdCriterion.vlanId());
739 + treatmentMpls.popVlan();
594 treatmentMpls.transition(mplsTableId); 740 treatmentMpls.transition(mplsTableId);
595 FlowRule ruleMpls = DefaultFlowRule.builder() 741 FlowRule ruleMpls = DefaultFlowRule.builder()
596 .forDevice(deviceId).withSelector(selectorMpls.build()) 742 .forDevice(deviceId).withSelector(selectorMpls.build())
597 .withTreatment(treatmentMpls.build()) 743 .withTreatment(treatmentMpls.build())
598 .withPriority(filt.priority()).fromApp(applicationId) 744 .withPriority(filt.priority()).fromApp(applicationId)
599 .makePermanent().forTable(tmacTableId).build(); 745 .makePermanent().forTable(tmacTableId).build();
600 - log.debug("adding MPLS ETH rule for MAC: {}", e.mac()); 746 + log.debug("adding MPLS ETH rule for MAC: {}", ethCriterion.mac());
601 rules.add(ruleMpls); 747 rules.add(ruleMpls);
602 748
603 return rules; 749 return rules;
604 } 750 }
605 751
606 - protected List<FlowRule> processVlanIdFilter(Criterion c, 752 + protected List<FlowRule> processVlanIdFilter(VlanIdCriterion vlanIdCriterion,
607 FilteringObjective filt, 753 FilteringObjective filt,
754 + VlanId assignedVlan,
608 ApplicationId applicationId) { 755 ApplicationId applicationId) {
609 List<FlowRule> rules = new ArrayList<>(); 756 List<FlowRule> rules = new ArrayList<>();
610 - VlanIdCriterion v = (VlanIdCriterion) c; 757 + log.debug("adding rule for VLAN: {}", vlanIdCriterion.vlanId());
611 - log.debug("adding rule for VLAN: {}", v.vlanId());
612 TrafficSelector.Builder selector = DefaultTrafficSelector 758 TrafficSelector.Builder selector = DefaultTrafficSelector
613 .builder(); 759 .builder();
614 TrafficTreatment.Builder treatment = DefaultTrafficTreatment 760 TrafficTreatment.Builder treatment = DefaultTrafficTreatment
615 .builder(); 761 .builder();
616 PortCriterion p = (PortCriterion) filt.key(); 762 PortCriterion p = (PortCriterion) filt.key();
617 - if (v.vlanId() != VlanId.NONE) { 763 + if (vlanIdCriterion.vlanId() != VlanId.NONE) {
618 - selector.matchVlanId(v.vlanId()); 764 + selector.matchVlanId(vlanIdCriterion.vlanId());
619 selector.matchInPort(p.port()); 765 selector.matchInPort(p.port());
620 treatment.deferred().popVlan(); 766 treatment.deferred().popVlan();
767 + } else {
768 + selector.matchInPort(p.port());
769 + treatment.immediate().pushVlan().setVlanId(assignedVlan);
621 } 770 }
622 treatment.transition(tmacTableId); 771 treatment.transition(tmacTableId);
623 FlowRule rule = DefaultFlowRule.builder().forDevice(deviceId) 772 FlowRule rule = DefaultFlowRule.builder().forDevice(deviceId)
...@@ -641,30 +790,79 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -641,30 +790,79 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
641 fail(filt, ObjectiveError.UNKNOWN); 790 fail(filt, ObjectiveError.UNKNOWN);
642 return; 791 return;
643 } 792 }
793 +
794 + EthCriterion ethCriterion = null;
795 + VlanIdCriterion vlanIdCriterion = null;
796 +
644 // convert filtering conditions for switch-intfs into flowrules 797 // convert filtering conditions for switch-intfs into flowrules
645 FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); 798 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
646 - for (Criterion c : filt.conditions()) { 799 +
647 - if (c.type() == Criterion.Type.ETH_DST) { 800 + for (Criterion criterion : filt.conditions()) {
648 - for (FlowRule rule : processEthDstFilter(c, 801 + if (criterion.type() == Criterion.Type.ETH_DST) {
649 - filt, 802 + ethCriterion = (EthCriterion) criterion;
650 - applicationId)) { 803 + } else if (criterion.type() == Criterion.Type.VLAN_VID) {
651 - ops = install ? ops.add(rule) : ops.remove(rule); 804 + vlanIdCriterion = (VlanIdCriterion) criterion;
652 - } 805 + } else if (criterion.type() == Criterion.Type.IPV4_DST) {
653 - } else if (c.type() == Criterion.Type.VLAN_VID) {
654 - for (FlowRule rule : processVlanIdFilter(c,
655 - filt,
656 - applicationId)) {
657 - ops = install ? ops.add(rule) : ops.remove(rule);
658 - }
659 - } else if (c.type() == Criterion.Type.IPV4_DST) {
660 log.debug("driver does not process IP filtering rules as it " + 806 log.debug("driver does not process IP filtering rules as it " +
661 "sends all misses in the IP table to the controller"); 807 "sends all misses in the IP table to the controller");
662 } else { 808 } else {
663 log.warn("Driver does not currently process filtering condition" 809 log.warn("Driver does not currently process filtering condition"
664 - + " of type: {}", c.type()); 810 + + " of type: {}", criterion.type());
665 fail(filt, ObjectiveError.UNSUPPORTED); 811 fail(filt, ObjectiveError.UNSUPPORTED);
666 } 812 }
667 } 813 }
814 +
815 + VlanId assignedVlan = null;
816 + if (vlanIdCriterion != null && vlanIdCriterion.vlanId() == VlanId.NONE) {
817 + // Assign a VLAN ID to untagged packets
818 + if (filt.meta() == null) {
819 + log.error("Missing metadata in filtering objective required "
820 + + "for vlan assignment in dev {}", deviceId);
821 + fail(filt, ObjectiveError.BADPARAMS);
822 + return;
823 + }
824 + for (Instruction i : filt.meta().allInstructions()) {
825 + if (i instanceof ModVlanIdInstruction) {
826 + assignedVlan = ((ModVlanIdInstruction) i).vlanId();
827 + }
828 + }
829 + if (assignedVlan == null) {
830 + log.error("Driver requires an assigned vlan-id to tag incoming "
831 + + "untagged packets. Not processing vlan filters on "
832 + + "device {}", deviceId);
833 + fail(filt, ObjectiveError.BADPARAMS);
834 + return;
835 + }
836 + }
837 +
838 + if (ethCriterion == null) {
839 + log.debug("filtering objective missing dstMac, cannot program TMAC table");
840 + } else {
841 + for (FlowRule tmacRule : processEthDstFilter(ethCriterion,
842 + vlanIdCriterion,
843 + filt,
844 + assignedVlan,
845 + applicationId)) {
846 + log.debug("adding MAC filtering rules in TMAC table: {} for dev: {}",
847 + tmacRule, deviceId);
848 + ops = install ? ops.add(tmacRule) : ops.remove(tmacRule);
849 + }
850 + }
851 +
852 + if (ethCriterion == null || vlanIdCriterion == null) {
853 + log.debug("filtering objective missing dstMac or vlan, cannot program"
854 + + "Vlan Table");
855 + } else {
856 + for (FlowRule vlanRule : processVlanIdFilter(vlanIdCriterion,
857 + filt,
858 + assignedVlan,
859 + applicationId)) {
860 + log.debug("adding VLAN filtering rule in VLAN table: {} for dev: {}",
861 + vlanRule, deviceId);
862 + ops = install ? ops.add(vlanRule) : ops.remove(vlanRule);
863 + }
864 + }
865 +
668 // apply filtering flow rules 866 // apply filtering flow rules
669 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { 867 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
670 @Override 868 @Override
...@@ -686,10 +884,10 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -686,10 +884,10 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
686 protected void setTableMissEntries() { 884 protected void setTableMissEntries() {
687 // set all table-miss-entries 885 // set all table-miss-entries
688 populateTableMissEntry(vlanTableId, true, false, false, -1); 886 populateTableMissEntry(vlanTableId, true, false, false, -1);
689 - populateTableMissEntry(tmacTableId, true, false, false, -1); 887 + populateTableMissEntry(tmacTableId, false, false, true, dstMacTableId);
690 - populateTableMissEntry(ipv4UnicastTableId, false, true, true, 888 + populateTableMissEntry(ipv4UnicastTableId, false, true, true, aclTableId);
691 - aclTableId);
692 populateTableMissEntry(mplsTableId, false, true, true, aclTableId); 889 populateTableMissEntry(mplsTableId, false, true, true, aclTableId);
890 + populateTableMissEntry(dstMacTableId, false, false, true, aclTableId);
693 populateTableMissEntry(aclTableId, false, false, false, -1); 891 populateTableMissEntry(aclTableId, false, false, false, -1);
694 } 892 }
695 893
......
...@@ -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");
......