CORD-348 multicast support in SegmentRouting and vRouter
In this submission:
* Setup/teardown multicast route according to SinkAdded/SinkRemoved event
- ingressVlan and egressVlan is configurable through network config
* Change behavior of OFDPA VLAN assignment
- Always use the VLAN in metadata if present
* Bugfix of writing immutable object
NOT in this submission (coming soon):
* Error handling (e.g. link/device failure recovery)
Change-Id: I9be11af04eb2d6456b865c7e59e96cc02370f846
diff --git a/apps/routing/src/main/java/org/onosproject/routing/impl/SingleSwitchFibInstaller.java b/apps/routing/src/main/java/org/onosproject/routing/impl/SingleSwitchFibInstaller.java
index 473450d..f0649b9 100644
--- a/apps/routing/src/main/java/org/onosproject/routing/impl/SingleSwitchFibInstaller.java
+++ b/apps/routing/src/main/java/org/onosproject/routing/impl/SingleSwitchFibInstaller.java
@@ -29,11 +29,13 @@
import org.onlab.packet.Ethernet;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onlab.util.Tools;
import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
+import org.onosproject.incubator.net.config.basics.McastConfig;
import org.onosproject.incubator.net.intf.Interface;
import org.onosproject.incubator.net.intf.InterfaceEvent;
import org.onosproject.incubator.net.intf.InterfaceListener;
@@ -44,9 +46,12 @@
import org.onosproject.incubator.net.routing.RouteService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.config.ConfigFactory;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
+import org.onosproject.net.config.NetworkConfigRegistry;
import org.onosproject.net.config.NetworkConfigService;
+import org.onosproject.net.config.basics.SubjectFactories;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
@@ -102,6 +107,9 @@
protected NetworkConfigService networkConfigService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected NetworkConfigRegistry networkConfigRegistry;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ComponentConfigService componentConfigService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -123,6 +131,7 @@
private List<String> interfaces;
+ private ApplicationId coreAppId;
private ApplicationId routerAppId;
// Reference count for how many times a next hop is used by a route
@@ -138,13 +147,25 @@
private InternalInterfaceListener internalInterfaceList = new InternalInterfaceListener();
private InternalRouteListener routeListener = new InternalRouteListener();
+ private ConfigFactory<ApplicationId, McastConfig> mcastConfigFactory =
+ new ConfigFactory<ApplicationId, McastConfig>(SubjectFactories.APP_SUBJECT_FACTORY,
+ McastConfig.class, "multicast") {
+ @Override
+ public McastConfig createConfig() {
+ return new McastConfig();
+ }
+ };
+
@Activate
protected void activate(ComponentContext context) {
componentConfigService.registerProperties(getClass());
modified(context);
+ coreAppId = coreService.registerApplication(CoreService.CORE_APP_NAME);
routerAppId = coreService.registerApplication(RoutingService.ROUTER_APP_ID);
+ networkConfigRegistry.registerConfigFactory(mcastConfigFactory);
+
deviceListener = new InternalDeviceListener();
deviceService.addListener(deviceListener);
@@ -368,6 +389,7 @@
}
createFilteringObjective(install, intf);
+ createMcastFilteringObjective(install, intf);
}
}
@@ -380,10 +402,14 @@
}
createFilteringObjective(install, intf);
+ createMcastFilteringObjective(install, intf);
}
//create filtering objective for interface
private void createFilteringObjective(boolean install, Interface intf) {
+ VlanId assignedVlan = (egressVlan().equals(VlanId.NONE)) ?
+ VlanId.vlanId(ASSIGNED_VLAN) :
+ egressVlan();
FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
// first add filter for the interface
@@ -393,12 +419,12 @@
fob.withPriority(PRIORITY_OFFSET);
if (intf.vlan() == VlanId.NONE) {
TrafficTreatment tt = DefaultTrafficTreatment.builder()
- .pushVlan().setVlanId(VlanId.vlanId(ASSIGNED_VLAN)).build();
+ .pushVlan().setVlanId(assignedVlan).build();
fob.withMeta(tt);
}
-
fob.permit().fromApp(routerAppId);
sendFilteringObjective(install, fob, intf);
+
if (controlPlaneConnectPoint != null) {
// then add the same mac/vlan filters for control-plane connect point
fob.withKey(Criteria.matchInPort(controlPlaneConnectPoint.port()));
@@ -406,6 +432,27 @@
}
}
+ //create filtering objective for multicast traffic
+ private void createMcastFilteringObjective(boolean install, Interface intf) {
+ VlanId assignedVlan = (egressVlan().equals(VlanId.NONE)) ?
+ VlanId.vlanId(ASSIGNED_VLAN) :
+ egressVlan();
+
+ FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
+ // first add filter for the interface
+ fob.withKey(Criteria.matchInPort(intf.connectPoint().port()))
+ .addCondition(Criteria.matchEthDstMasked(MacAddress.IPV4_MULTICAST,
+ MacAddress.IPV4_MULTICAST_MASK))
+ .addCondition(Criteria.matchVlanId(ingressVlan()));
+ fob.withPriority(PRIORITY_OFFSET);
+ TrafficTreatment tt = DefaultTrafficTreatment.builder()
+ .pushVlan().setVlanId(assignedVlan).build();
+ fob.withMeta(tt);
+
+ fob.permit().fromApp(routerAppId);
+ sendFilteringObjective(install, fob, intf);
+ }
+
private void sendFilteringObjective(boolean install, FilteringObjective.Builder fob,
Interface intf) {
@@ -419,6 +466,18 @@
flowObjectiveService.filter(deviceId, filter);
}
+ private VlanId ingressVlan() {
+ McastConfig mcastConfig =
+ networkConfigService.getConfig(coreAppId, McastConfig.class);
+ return (mcastConfig != null) ? mcastConfig.ingressVlan() : VlanId.NONE;
+ }
+
+ private VlanId egressVlan() {
+ McastConfig mcastConfig =
+ networkConfigService.getConfig(coreAppId, McastConfig.class);
+ return (mcastConfig != null) ? mcastConfig.egressVlan() : VlanId.NONE;
+ }
+
private class InternalRouteListener implements RouteListener {
@Override
public void event(RouteEvent event) {
@@ -490,7 +549,6 @@
}
private class InternalInterfaceListener implements InterfaceListener {
-
@Override
public void event(InterfaceEvent event) {
Interface intf = event.subject();