Luca Prete
Committed by Gerrit Code Review

Refactor ProxyManager Tests and added functionality to manage traffic coming and…

… going through vlan interfaces

Change-Id: I8d748c42b48d0956c670be12ff2742cb2022fa62
...@@ -53,6 +53,7 @@ import org.slf4j.Logger; ...@@ -53,6 +53,7 @@ import org.slf4j.Logger;
53 53
54 import java.nio.ByteBuffer; 54 import java.nio.ByteBuffer;
55 import java.util.Set; 55 import java.util.Set;
56 +import java.util.stream.Collectors;
56 57
57 import static com.google.common.base.Preconditions.checkArgument; 58 import static com.google.common.base.Preconditions.checkArgument;
58 import static com.google.common.base.Preconditions.checkNotNull; 59 import static com.google.common.base.Preconditions.checkNotNull;
...@@ -199,11 +200,49 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -199,11 +200,49 @@ public class ProxyArpManager implements ProxyArpService {
199 return; 200 return;
200 } 201 }
201 202
203 + // If the packets has a vlanId look if there are some other
204 + // interfaces in the configuration on the same vlan and broadcast
205 + // the packet out just of through those interfaces.
206 + VlanId vlanId = context.vlan();
207 +
208 + Set<Interface> filteredVlanInterfaces =
209 + filterVlanInterfacesNoIp(interfaceService.getInterfacesByVlan(vlanId));
210 +
211 + if (vlanId != null
212 + && !vlanId.equals(VlanId.NONE)
213 + && confContainsVlans(vlanId, context.inPort())) {
214 + vlanFlood(context.packet(), filteredVlanInterfaces, context.inPort);
215 + return;
216 + }
217 +
202 // The request couldn't be resolved. 218 // The request couldn't be resolved.
203 // Flood the request on all ports except the incoming port. 219 // Flood the request on all ports except the incoming port.
204 flood(context.packet(), context.inPort()); 220 flood(context.packet(), context.inPort());
205 } 221 }
206 222
223 + private Set<Interface> filterVlanInterfacesNoIp(Set<Interface> vlanInterfaces) {
224 + return vlanInterfaces
225 + .stream()
226 + .filter(intf -> intf.ipAddresses().isEmpty())
227 + .collect(Collectors.toSet());
228 + }
229 +
230 + /**
231 + * States if the interface configuration contains more than one interface configured
232 + * on a specific vlan, including the interface passed as argument.
233 + *
234 + * @param vlanId the vlanid to look for in the interface configuration
235 + * @param connectPoint the connect point to exclude from the search
236 + * @return true if interfaces are found. False otherwise
237 + */
238 + private boolean confContainsVlans(VlanId vlanId, ConnectPoint connectPoint) {
239 + Set<Interface> vlanInterfaces = interfaceService.getInterfacesByVlan(vlanId);
240 + return interfaceService.getInterfacesByVlan(vlanId)
241 + .stream()
242 + .anyMatch(intf -> intf.connectPoint().equals(connectPoint) && intf.ipAddresses().isEmpty())
243 + && vlanInterfaces.size() > 1;
244 + }
245 +
207 /** 246 /**
208 * Builds and sends a reply message given a request context and the resolved 247 * Builds and sends a reply message given a request context and the resolved
209 * MAC address to answer with. 248 * MAC address to answer with.
...@@ -259,14 +298,29 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -259,14 +298,29 @@ public class ProxyArpManager implements ProxyArpService {
259 /** 298 /**
260 * Returns whether the given port has any IP addresses configured or not. 299 * Returns whether the given port has any IP addresses configured or not.
261 * 300 *
262 - * @param port the port to check 301 + * @param connectPoint the port to check
263 * @return true if the port has at least one IP address configured, 302 * @return true if the port has at least one IP address configured,
264 - * otherwise false 303 + * false otherwise
304 + */
305 + private boolean hasIpAddress(ConnectPoint connectPoint) {
306 + return interfaceService.getInterfacesByPort(connectPoint)
307 + .stream()
308 + .flatMap(intf -> intf.ipAddresses().stream())
309 + .findAny()
310 + .isPresent();
311 + }
312 +
313 + /**
314 + * Returns whether the given port has any VLAN configured or not.
315 + *
316 + * @param connectPoint the port to check
317 + * @return true if the port has at least one VLAN configured,
318 + * false otherwise
265 */ 319 */
266 - private boolean hasIpAddress(ConnectPoint port) { 320 + private boolean hasVlan(ConnectPoint connectPoint) {
267 - return interfaceService.getInterfacesByPort(port) 321 + return interfaceService.getInterfacesByPort(connectPoint)
268 .stream() 322 .stream()
269 - .map(intf -> intf.ipAddresses()) 323 + .filter(intf -> !intf.vlan().equals(VlanId.NONE))
270 .findAny() 324 .findAny()
271 .isPresent(); 325 .isPresent();
272 } 326 }
...@@ -322,6 +376,30 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -322,6 +376,30 @@ public class ProxyArpManager implements ProxyArpService {
322 } 376 }
323 377
324 /** 378 /**
379 + * Flood the arp request at all edges on a specifc VLAN.
380 + *
381 + * @param request the arp request
382 + * @param dsts the destination interfaces
383 + * @param inPort the connect point the arp request was received on
384 + */
385 + private void vlanFlood(Ethernet request, Set<Interface> dsts, ConnectPoint inPort) {
386 + TrafficTreatment.Builder builder = null;
387 + ByteBuffer buf = ByteBuffer.wrap(request.serialize());
388 +
389 + for (Interface intf : dsts) {
390 + ConnectPoint cPoint = intf.connectPoint();
391 + if (cPoint.equals(inPort)) {
392 + continue;
393 + }
394 +
395 + builder = DefaultTrafficTreatment.builder();
396 + builder.setOutput(cPoint.port());
397 + packetService.emit(new DefaultOutboundPacket(cPoint.deviceId(),
398 + builder.build(), buf));
399 + }
400 + }
401 +
402 + /**
325 * Flood the arp request at all edges in the network. 403 * Flood the arp request at all edges in the network.
326 * 404 *
327 * @param request the arp request 405 * @param request the arp request
...@@ -332,7 +410,9 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -332,7 +410,9 @@ public class ProxyArpManager implements ProxyArpService {
332 ByteBuffer buf = ByteBuffer.wrap(request.serialize()); 410 ByteBuffer buf = ByteBuffer.wrap(request.serialize());
333 411
334 for (ConnectPoint connectPoint : edgeService.getEdgePoints()) { 412 for (ConnectPoint connectPoint : edgeService.getEdgePoints()) {
335 - if (hasIpAddress(connectPoint) || connectPoint.equals(inPort)) { 413 + if (hasIpAddress(connectPoint)
414 + || hasVlan(connectPoint)
415 + || connectPoint.equals(inPort)) {
336 continue; 416 continue;
337 } 417 }
338 418
......