[ONOS-5298] New VPLS NeighbourHandler to support multiple VLANs
Change-Id: I5c809b9c108760defc666b9f5e9d2a17c64047eb
diff --git a/apps/vpls/src/main/java/org/onosproject/vpls/VplsNeighbourHandler.java b/apps/vpls/src/main/java/org/onosproject/vpls/VplsNeighbourHandler.java
index 69b8e34..d706dca 100644
--- a/apps/vpls/src/main/java/org/onosproject/vpls/VplsNeighbourHandler.java
+++ b/apps/vpls/src/main/java/org/onosproject/vpls/VplsNeighbourHandler.java
@@ -16,8 +16,7 @@
package org.onosproject.vpls;
-import com.google.common.collect.Maps;
-
+import com.google.common.collect.SetMultimap;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
@@ -33,20 +32,28 @@
import org.onosproject.incubator.net.neighbour.NeighbourMessageHandler;
import org.onosproject.incubator.net.neighbour.NeighbourResolutionService;
import org.onosproject.net.Host;
+import org.onosproject.net.config.NetworkConfigEvent;
+import org.onosproject.net.config.NetworkConfigListener;
+import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.host.HostService;
+import org.onosproject.vpls.config.VplsConfigurationService;
import org.slf4j.Logger;
-import java.util.Map;
+import java.util.Collection;
+import java.util.Set;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Handles neighbour messages for VPLS use case.
- * Handlers will be changed automatically by interface or network configuration
- * events.
+ * Handlers will be changed automatically by interface or network configuration events.
*/
@Component(immediate = true)
public class VplsNeighbourHandler {
+ private static final String UNKNOWN_CONTEXT = "Unknown context type: {}";
+
+ private static final String CAN_NOT_FIND_NETWORK =
+ "Cannot find VPLS for port {} with VLAN Id {}.";
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
@@ -57,16 +64,22 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected NeighbourResolutionService neighbourService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected VplsConfigurationService vplsConfigService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected NetworkConfigService configService;
+
private VplsInterfaceListener interfaceListener
= new VplsInterfaceListener();
- private VplsNeighbourMessageHandler neighbourHandler =
+ protected VplsNeighbourMessageHandler neighbourHandler =
new VplsNeighbourMessageHandler();
- private final Logger log = getLogger(getClass());
+ protected VplsConfigListener configListener =
+ new VplsConfigListener();
- private Map<Interface, NeighbourMessageHandler> neighbourHandlers =
- Maps.newHashMap();
+ private final Logger log = getLogger(getClass());
private ApplicationId appId;
@@ -75,42 +88,29 @@
protected void activate() {
appId = coreService.registerApplication(Vpls.VPLS_APP);
interfaceService.addListener(interfaceListener);
-
- interfaceService.getInterfaces().forEach(intf -> {
- neighbourHandlers.put(intf, neighbourHandler);
-
- neighbourService.registerNeighbourHandler(intf, neighbourHandler, appId);
- });
-
- log.debug("Activated");
+ configService.addListener(configListener);
+ configNeighbourHandler();
}
@Deactivate
protected void deactivate() {
interfaceService.removeListener(interfaceListener);
- neighbourHandlers.entrySet().forEach(e -> {
- neighbourService.unregisterNeighbourHandler(e.getKey(), e.getValue(), appId);
- });
- log.debug("Deactivated");
+ configService.removeListener(configListener);
+ neighbourService.unregisterNeighbourHandlers(appId);
}
- private void configNeighbourHandler(Interface intf,
- NeighbourMessageHandler handler,
- InterfaceEvent.Type eventType) {
- switch (eventType) {
- case INTERFACE_ADDED:
- neighbourHandlers.put(intf, handler);
- neighbourService.registerNeighbourHandler(intf, handler, appId);
- break;
- case INTERFACE_REMOVED:
- neighbourHandlers.remove(intf, handler);
- neighbourService.unregisterNeighbourHandler(intf, handler, appId);
- break;
- case INTERFACE_UPDATED:
- break;
- default:
- break;
- }
+ private void configNeighbourHandler() {
+ neighbourService.unregisterNeighbourHandlers(appId);
+ Set<Interface> interfaces = vplsConfigService.getAllInterfaces();
+
+ interfaceService.getInterfaces()
+ .stream()
+ .filter(interfaces::contains)
+ .forEach(intf -> {
+ neighbourService.registerNeighbourHandler(intf,
+ neighbourHandler,
+ appId);
+ });
}
/**
@@ -124,34 +124,84 @@
switch (context.type()) {
case REQUEST:
- interfaceService.getInterfacesByVlan(context.vlan())
- .stream()
- .filter(intf -> !context.inPort().equals(intf.connectPoint()))
- .forEach(context::forward);
+ handleRequest(context);
break;
+
case REPLY:
- hostService.getHostsByMac(context.dstMac())
- .stream()
- .filter(host -> host.vlan().equals(context.vlan()))
- .map(Host::location)
- .forEach(context::forward);
+ handleReply(context, hostService);
break;
default:
- log.warn("Unknown context type: {}", context.type());
+ log.warn(UNKNOWN_CONTEXT, context.type());
break;
}
}
}
/**
+ * Handles request messages.
+ *
+ * @param context the message context
+ */
+ protected void handleRequest(NeighbourMessageContext context) {
+
+ SetMultimap<String, Interface> vplsNetwork =
+ vplsConfigService.getVplsNetwork(context.vlan(), context.inPort());
+
+ if (vplsNetwork != null) {
+ Collection<Interface> vplsInterfaces = vplsNetwork.values();
+ vplsInterfaces.stream()
+ .filter(intf -> !context.inPort().equals(intf.connectPoint()))
+ .forEach(context::forward);
+
+ } else {
+ log.debug(CAN_NOT_FIND_NETWORK, context.inPort(), context.vlan());
+ }
+ }
+
+ /**
+ * Handles reply messages between VLAN tagged interfaces.
+ *
+ * @param context the message context
+ * @param hostService the host service
+ */
+ protected void handleReply(NeighbourMessageContext context,
+ HostService hostService) {
+
+ SetMultimap<String, Interface> vplsNetwork =
+ vplsConfigService.getVplsNetwork(context.vlan(), context.inPort());
+
+ Set<Host> hosts = hostService.getHostsByMac(context.dstMac());
+ if (vplsNetwork != null) {
+ Collection<Interface> vplsInterfaces = vplsNetwork.values();
+ hosts.forEach(host -> vplsInterfaces.stream()
+ .filter(intf -> intf.connectPoint().equals(host.location()))
+ .filter(intf -> intf.vlan().equals(host.vlan()))
+ .forEach(context::forward));
+ } else {
+ log.debug(CAN_NOT_FIND_NETWORK, context.inPort(), context.vlan());
+ }
+ }
+
+ /**
* Listener for interface configuration events.
*/
private class VplsInterfaceListener implements InterfaceListener {
@Override
public void event(InterfaceEvent event) {
- configNeighbourHandler(event.subject(), neighbourHandler, event.type());
+ configNeighbourHandler();
+ }
+ }
+
+ /**
+ * Listener for network configuration events.
+ */
+ private class VplsConfigListener implements NetworkConfigListener {
+
+ @Override
+ public void event(NetworkConfigEvent event) {
+ configNeighbourHandler();
}
}