[SEBA-815]Multi Tcont support by OLT app.
[VOL-2525] Fixing the OLT app meter removal and optimizing the bandwith profile to meter map with a Multimap
Change-Id: I024ef2fcb3d3e59cc86bd2088726ae513fcff796
diff --git a/app/src/main/java/org/opencord/olt/impl/Olt.java b/app/src/main/java/org/opencord/olt/impl/Olt.java
index 3775060..e392b41 100644
--- a/app/src/main/java/org/opencord/olt/impl/Olt.java
+++ b/app/src/main/java/org/opencord/olt/impl/Olt.java
@@ -16,15 +16,9 @@
package org.opencord.olt.impl;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
-import org.onlab.packet.EthType;
-import org.onlab.packet.IPv4;
-import org.onlab.packet.IPv6;
-import org.onlab.packet.TpPort;
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;
@@ -39,43 +33,23 @@
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flow.criteria.Criteria;
-import org.onosproject.net.flowobjective.DefaultFilteringObjective;
-import org.onosproject.net.flowobjective.DefaultForwardingObjective;
-import org.onosproject.net.flowobjective.FilteringObjective;
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.flowobjective.Objective;
import org.onosproject.net.flowobjective.ObjectiveContext;
import org.onosproject.net.flowobjective.ObjectiveError;
-import org.onosproject.net.meter.Band;
-import org.onosproject.net.meter.DefaultBand;
-import org.onosproject.net.meter.DefaultMeterRequest;
-import org.onosproject.net.meter.Meter;
-import org.onosproject.net.meter.MeterContext;
-import org.onosproject.net.meter.MeterEvent;
-import org.onosproject.net.meter.MeterFailReason;
import org.onosproject.net.meter.MeterId;
-import org.onosproject.net.meter.MeterKey;
-import org.onosproject.net.meter.MeterListener;
-import org.onosproject.net.meter.MeterRequest;
-import org.onosproject.net.meter.MeterService;
-import org.onosproject.store.serializers.KryoNamespaces;
-import org.onosproject.store.service.ConsistentMultimap;
-import org.onosproject.store.service.Serializer;
-import org.onosproject.store.service.StorageService;
import org.opencord.olt.AccessDeviceEvent;
import org.opencord.olt.AccessDeviceListener;
import org.opencord.olt.AccessDeviceService;
import org.opencord.olt.AccessSubscriberId;
+import org.opencord.olt.internalapi.AccessDeviceFlowService;
+import org.opencord.olt.internalapi.AccessDeviceMeterService;
import org.opencord.sadis.BandwidthProfileInformation;
import org.opencord.sadis.BaseInformationService;
import org.opencord.sadis.SadisService;
import org.opencord.sadis.SubscriberAndDeviceInformation;
+import org.opencord.sadis.UniTagInformation;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
@@ -85,10 +59,7 @@
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.slf4j.Logger;
-import java.util.AbstractMap;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
import java.util.Dictionary;
import java.util.List;
import java.util.Map;
@@ -97,34 +68,15 @@
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Strings.isNullOrEmpty;
import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
import static org.onlab.util.Tools.get;
import static org.onlab.util.Tools.groupedThreads;
-import static org.opencord.olt.impl.OsgiPropertyConstants.DEFAULT_BP_ID;
-import static org.opencord.olt.impl.OsgiPropertyConstants.DEFAULT_BP_ID_DEFAULT;
-import static org.opencord.olt.impl.OsgiPropertyConstants.DEFAULT_TP_ID;
-import static org.opencord.olt.impl.OsgiPropertyConstants.DEFAULT_TP_ID_DEFAULT;
-import static org.opencord.olt.impl.OsgiPropertyConstants.DEFAULT_VLAN;
-import static org.opencord.olt.impl.OsgiPropertyConstants.DEFAULT_VLAN_DEFAULT;
-import static org.opencord.olt.impl.OsgiPropertyConstants.DELETE_METERS;
-import static org.opencord.olt.impl.OsgiPropertyConstants.DELETE_METERS_DEFAULT;
-import static org.opencord.olt.impl.OsgiPropertyConstants.ENABLE_DHCP_ON_PROVISIONING;
-import static org.opencord.olt.impl.OsgiPropertyConstants.ENABLE_DHCP_ON_PROVISIONING_DEFAULT;
-import static org.opencord.olt.impl.OsgiPropertyConstants.ENABLE_DHCP_V4;
-import static org.opencord.olt.impl.OsgiPropertyConstants.ENABLE_DHCP_V4_DEFAULT;
-import static org.opencord.olt.impl.OsgiPropertyConstants.ENABLE_DHCP_V6;
-import static org.opencord.olt.impl.OsgiPropertyConstants.ENABLE_DHCP_V6_DEFAULT;
-import static org.opencord.olt.impl.OsgiPropertyConstants.ENABLE_EAPOL;
-import static org.opencord.olt.impl.OsgiPropertyConstants.ENABLE_EAPOL_DEFAULT;
-import static org.opencord.olt.impl.OsgiPropertyConstants.ENABLE_IGMP_ON_PROVISIONING;
-import static org.opencord.olt.impl.OsgiPropertyConstants.ENABLE_IGMP_ON_PROVISIONING_DEFAULT;
+import static org.opencord.olt.impl.OsgiPropertyConstants.*;
import static org.slf4j.LoggerFactory.getLogger;
/**
@@ -132,15 +84,8 @@
*/
@Component(immediate = true,
property = {
- DEFAULT_VLAN + ":Integer=" + DEFAULT_VLAN_DEFAULT,
- ENABLE_DHCP_ON_PROVISIONING + ":Boolean=" + ENABLE_DHCP_ON_PROVISIONING_DEFAULT,
- ENABLE_DHCP_V4 + ":Boolean=" + ENABLE_DHCP_V4_DEFAULT,
- ENABLE_DHCP_V6 + ":Boolean=" + ENABLE_DHCP_V6_DEFAULT,
- ENABLE_IGMP_ON_PROVISIONING + ":Boolean=" + ENABLE_IGMP_ON_PROVISIONING_DEFAULT,
- DELETE_METERS + ":Boolean=" + DELETE_METERS_DEFAULT,
- DEFAULT_TP_ID + ":Integer=" + DEFAULT_TP_ID_DEFAULT,
DEFAULT_BP_ID + ":String=" + DEFAULT_BP_ID_DEFAULT,
- ENABLE_EAPOL + ":Boolean=" + ENABLE_EAPOL_DEFAULT,
+ DEFAULT_MCAST_SERVICE_NAME + ":String=" + DEFAULT_MCAST_SERVICE_NAME_DEFAULT,
})
public class Olt
extends AbstractListenerManager<AccessDeviceEvent, AccessDeviceListener>
@@ -148,12 +93,7 @@
private static final String APP_NAME = "org.opencord.olt";
private static final short EAPOL_DEFAULT_VLAN = 4091;
- private static final String ADDITIONAL_VLANS = "additional-vlans";
private static final String NO_UPLINK_PORT = "No uplink port found for OLT device {}";
- private static final String INSTALLED = "installed";
- private static final String REMOVED = "removed";
- private static final String INSTALLATION = "installation";
- private static final String REMOVAL = "removal";
private final Logger log = getLogger(getClass());
@@ -176,45 +116,10 @@
protected SadisService sadisService;
@Reference(cardinality = ReferenceCardinality.MANDATORY)
- protected MeterService meterService;
+ protected AccessDeviceFlowService oltFlowService;
@Reference(cardinality = ReferenceCardinality.MANDATORY)
- protected StorageService storageService;
-
- /**
- * Default VLAN RG<->ONU traffic.
- **/
- private int defaultVlan = DEFAULT_VLAN_DEFAULT;
-
- /**
- * Create the DHCP Flow rules when a subscriber is provisioned.
- **/
- protected boolean enableDhcpOnProvisioning = ENABLE_DHCP_ON_PROVISIONING_DEFAULT;
-
- /**
- * Enable flows for DHCP v4.
- **/
- protected boolean enableDhcpV4 = ENABLE_DHCP_V4_DEFAULT;
-
- /**
- * Enable flows for DHCP v6.
- **/
- protected boolean enableDhcpV6 = ENABLE_DHCP_V6_DEFAULT;
-
- /**
- * Create IGMP Flow rules when a subscriber is provisioned.
- **/
- protected boolean enableIgmpOnProvisioning = ENABLE_IGMP_ON_PROVISIONING_DEFAULT;
-
- /**
- * Deleting Meters based on flow count statistics.
- **/
- protected boolean deleteMeters = DELETE_METERS_DEFAULT;
-
- /**
- * Default technology profile id that is used for authentication trap flows.
- **/
- protected int defaultTechProfileId = DEFAULT_TP_ID_DEFAULT;
+ protected AccessDeviceMeterService oltMeterService;
/**
* Default bandwidth profile id that is used for authentication trap flows.
@@ -222,49 +127,41 @@
protected String defaultBpId = DEFAULT_BP_ID_DEFAULT;
/**
- * Send EAPOL authentication trap flows before subscriber provisioning.
+ * Deleting Meters based on flow count statistics.
**/
- protected boolean enableEapol = ENABLE_EAPOL_DEFAULT;
+ protected String multicastServiceName = DEFAULT_MCAST_SERVICE_NAME;
private final DeviceListener deviceListener = new InternalDeviceListener();
- private final MeterListener meterListener = new InternalMeterListener();
- private ApplicationId appId;
protected BaseInformationService<SubscriberAndDeviceInformation> subsService;
private BaseInformationService<BandwidthProfileInformation> bpService;
- private Map<String, List<MeterKey>> bpInfoToMeter = new ConcurrentHashMap<>();
-
private ExecutorService oltInstallers = Executors.newFixedThreadPool(4,
- groupedThreads("onos/olt-service",
- "olt-installer-%d"));
-
- private ConsistentMultimap<ConnectPoint, Map.Entry<VlanId, VlanId>> additionalVlans;
+ groupedThreads("onos/olt-service",
+ "olt-installer-%d"));
protected ExecutorService eventExecutor;
- private Map<ConnectPoint, SubscriberAndDeviceInformation> programmedSubs;
- private Set<MeterKey> programmedMeters;
-
+ private Map<ConnectPoint, Set<UniTagInformation>> programmedSubs;
@Activate
public void activate(ComponentContext context) {
- eventExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/olt", "events-%d", log));
+ eventExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/olt",
+ "events-%d", log));
modified(context);
- appId = coreService.registerApplication(APP_NAME);
+ ApplicationId appId = coreService.registerApplication(APP_NAME);
// ensure that flow rules are purged from flow-store upon olt-disconnection
// when olt reconnects, the port-numbers may change for the ONUs
// making flows pushed earlier invalid
componentConfigService
.preSetProperty("org.onosproject.net.flow.impl.FlowRuleManager",
- "purgeOnDisconnection", "true");
+ "purgeOnDisconnection", "true");
componentConfigService
.preSetProperty("org.onosproject.net.meter.impl.MeterManager",
- "purgeOnDisconnection", "true");
+ "purgeOnDisconnection", "true");
componentConfigService.registerProperties(getClass());
programmedSubs = Maps.newConcurrentMap();
- programmedMeters = ConcurrentHashMap.newKeySet();
eventDispatcher.addSink(AccessDeviceEvent.class, listenerRegistry);
@@ -278,15 +175,7 @@
checkAndCreateDeviceFlows(d);
}
- additionalVlans = storageService.<ConnectPoint, Map.Entry<VlanId, VlanId>>consistentMultimapBuilder()
- .withName(ADDITIONAL_VLANS)
- .withSerializer(Serializer.using(Arrays.asList(KryoNamespaces.API),
- AbstractMap.SimpleEntry.class))
- .build();
-
deviceService.addListener(deviceListener);
- meterService.addListener(meterListener);
-
log.info("Started with Application ID {}", appId.id());
}
@@ -294,7 +183,6 @@
public void deactivate() {
componentConfigService.unregisterProperties(getClass(), false);
deviceService.removeListener(deviceListener);
- meterService.removeListener(meterListener);
eventDispatcher.removeSink(AccessDeviceEvent.class);
log.info("Stopped");
}
@@ -304,50 +192,16 @@
Dictionary<?, ?> properties = context != null ? context.getProperties() : new Properties();
try {
- String s = get(properties, "defaultVlan");
- defaultVlan = isNullOrEmpty(s) ? DEFAULT_VLAN_DEFAULT : Integer.parseInt(s.trim());
-
- Boolean o = Tools.isPropertyEnabled(properties, "enableDhcpOnProvisioning");
- if (o != null) {
- enableDhcpOnProvisioning = o;
- }
-
- Boolean v4 = Tools.isPropertyEnabled(properties, "enableDhcpV4");
- if (v4 != null) {
- enableDhcpV4 = v4;
- }
-
- Boolean v6 = Tools.isPropertyEnabled(properties, "enableDhcpV6");
- if (v6 != null) {
- enableDhcpV6 = v6;
- }
-
- Boolean p = Tools.isPropertyEnabled(properties, "enableIgmpOnProvisioning");
- if (p != null) {
- enableIgmpOnProvisioning = p;
- }
-
- log.info("DHCP Settings [enableDhcpOnProvisioning: {}, enableDhcpV4: {}, enableDhcpV6: {}]",
- enableDhcpOnProvisioning, enableDhcpV4, enableDhcpV6);
-
- Boolean d = Tools.isPropertyEnabled(properties, "deleteMeters");
- if (d != null) {
- deleteMeters = d;
- }
-
- String tpId = get(properties, "defaultTechProfileId");
- defaultTechProfileId = isNullOrEmpty(s) ? DEFAULT_TP_ID_DEFAULT : Integer.parseInt(tpId.trim());
-
String bpId = get(properties, "defaultBpId");
defaultBpId = bpId;
- Boolean eap = Tools.isPropertyEnabled(properties, "enableEapol");
- if (eap != null) {
- enableEapol = eap;
- }
+ String mcastSN = get(properties, "multicastServiceName");
+ multicastServiceName = mcastSN;
+
+ log.debug("OLT properties: DefaultBpId: {}, MulticastServiceName: {}", defaultBpId, multicastServiceName);
} catch (Exception e) {
- defaultVlan = DEFAULT_VLAN_DEFAULT;
+ log.error("Error while modifying the properties", e);
}
}
@@ -358,15 +212,7 @@
PortNumber subscriberPortNo = connectPoint.port();
checkNotNull(deviceService.getPort(deviceId, subscriberPortNo),
- "Invalid connect point");
-
- // If the subscriber is modified then first remove the previous and proceed
- SubscriberAndDeviceInformation subscriber = programmedSubs.get(connectPoint);
- if (subscriber != null) {
- log.info("Subscriber on connectionPoint {} was previously programmed, " +
- "remove it before adding again", connectPoint);
- removeSubscriber(connectPoint);
- }
+ "Invalid connect point:" + connectPoint);
// Find the subscriber on this connect point
SubscriberAndDeviceInformation sub = getSubscriber(connectPoint);
@@ -382,37 +228,17 @@
return false;
}
- SubscriberAndDeviceInformation prgSub = programmedSubs.get(connectPoint);
- if (prgSub != null) {
- log.warn("Subscriber {} on connectionPoint {} was previously programmed .. "
- + "taking no action. Note that updating a subscribers params "
- + "(vlans, bw, tpid etc) requires removing the subscriber"
- + "before re-provisioning the subscriber", prgSub.id(),
- connectPoint);
- return true;
- }
-
//delete Eapol authentication flow with default bandwidth
//wait until Eapol rule with defaultBpId is removed to install subscriber-based rules
- CompletableFuture<ObjectiveError> filterFuture = new CompletableFuture();
- processEapolFilteringObjectives(deviceId, subscriberPortNo, defaultBpId, filterFuture,
- VlanId.vlanId(EAPOL_DEFAULT_VLAN), false);
- // do not remove meter from bpInfoToMeter mapping as flows for other ONUs
- // could still be using it - this also prevents duplicate meters from being
- // created for the same bandwidth profile
- // we still need to remove from programmedMeters so the meter can be
- // deleted if its reference count drops to zero
- removeMeterIdFromPrgMeters(deviceId, defaultBpId);
-
//install subscriber flows
+ CompletableFuture<ObjectiveError> filterFuture = new CompletableFuture();
+ oltFlowService.processEapolFilteringObjectives(deviceId, subscriberPortNo, defaultBpId, filterFuture,
+ VlanId.vlanId(EAPOL_DEFAULT_VLAN), false);
filterFuture.thenAcceptAsync(filterStatus -> {
if (filterStatus == null) {
- provisionSubscriberBasedFlows(connectPoint, uplinkPort.number(), Optional.empty(), sub);
+ provisionUniTagList(connectPoint, uplinkPort.number(), sub);
}
});
-
- // cache subscriber info
- programmedSubs.put(connectPoint, sub);
return true;
}
@@ -425,10 +251,10 @@
DeviceId deviceId = connectPoint.deviceId();
PortNumber subscriberPortNo = connectPoint.port();
- SubscriberAndDeviceInformation subscriber = programmedSubs.get(connectPoint);
- if (subscriber == null) {
+ Set<UniTagInformation> uniTagInformationSet = programmedSubs.get(connectPoint);
+ if (uniTagInformationSet == null || uniTagInformationSet.isEmpty()) {
log.warn("Subscriber on connectionPoint {} was not previously programmed, " +
- "no need to remove it", connectPoint);
+ "no need to remove it", connectPoint);
return true;
}
@@ -439,53 +265,38 @@
return false;
}
- //delete dhcp & igmp trap flows
- MeterId upstreamMeterId = getMeterIdFromBpMapping(deviceId, subscriber.upstreamBandwidthProfile());
+ for (UniTagInformation uniTag : uniTagInformationSet) {
- // remove dhcp filters
- processDhcpFilteringObjectives(deviceId, subscriberPortNo,
- upstreamMeterId, subscriber.technologyProfileId(), false, true);
+ if (multicastServiceName.equals(uniTag.getServiceName())) {
+ continue;
+ }
- // remove igmp filters
- processIgmpFilteringObjectives(deviceId, subscriberPortNo,
- upstreamMeterId, subscriber.technologyProfileId(), false);
+ unprovisionVlans(deviceId, uplinkPort.number(), subscriberPortNo, uniTag);
- //unprovision vlans
- unprovisionVlans(deviceId, uplinkPort.number(), subscriberPortNo, subscriber, Optional.empty());
+ // re-install eapol with default bandwidth profile
+ oltFlowService.processEapolFilteringObjectives(deviceId, subscriberPortNo,
+ uniTag.getUpstreamBandwidthProfile(),
+ null, uniTag.getPonCTag(), false);
- // Remove if there are any flows for the additional Vlans
- Collection<? extends Map.Entry<VlanId, VlanId>> vlansList = additionalVlans.get(connectPoint).value();
-
- // Remove the flows for the additional vlans for this subscriber
- for (Map.Entry<VlanId, VlanId> vlans : vlansList) {
- unprovisionTransparentFlows(deviceId, uplinkPort.number(), subscriberPortNo,
- vlans.getValue(), vlans.getKey());
-
- // Remove it from the map also
- additionalVlans.remove(connectPoint, vlans);
+ Port port = deviceService.getPort(deviceId, subscriberPortNo);
+ if (port != null && port.isEnabled()) {
+ oltFlowService.processEapolFilteringObjectives(deviceId, subscriberPortNo, defaultBpId,
+ null, VlanId.vlanId(EAPOL_DEFAULT_VLAN), true);
+ } else {
+ log.debug("Port {} is no longer enabled or it's unavailable. Not "
+ + "reprogramming default eapol flow", connectPoint);
+ }
}
-
- // re-install eapol with default bandwidth profile
- processEapolFilteringObjectives(deviceId, subscriberPortNo,
- subscriber.upstreamBandwidthProfile(), null, subscriber.cTag(), false);
-
- Port port = deviceService.getPort(deviceId, subscriberPortNo);
- if (port != null && port.isEnabled()) {
- processEapolFilteringObjectives(deviceId, subscriberPortNo, defaultBpId,
- null, VlanId.vlanId(EAPOL_DEFAULT_VLAN), true);
- } else {
- log.debug("Port {} is no longer enabled or it's unavailable. Not "
- + "reprogramming default eapol flow", connectPoint);
- }
-
- programmedSubs.remove(connectPoint);
return true;
}
- @Override
- public boolean provisionSubscriber(AccessSubscriberId subscriberId, Optional<VlanId> sTag, Optional<VlanId> cTag) {
- log.info("Provisioning subscriber using subscriberId {}, sTag {}, cTag {}", subscriberId, sTag, cTag);
+ @Override
+ public boolean provisionSubscriber(AccessSubscriberId subscriberId, Optional<VlanId> sTag,
+ Optional<VlanId> cTag, Optional<Integer> tpId) {
+
+ log.info("Provisioning subscriber using subscriberId {}, sTag {}, cTag {}, tpId {}" +
+ "", subscriberId, sTag, cTag, tpId);
// Check if we can find the connect point to which this subscriber is connected
ConnectPoint subsPort = findSubscriberConnectPoint(subscriberId.toString());
@@ -496,31 +307,23 @@
if (!sTag.isPresent() && !cTag.isPresent()) {
return provisionSubscriber(subsPort);
- } else if (sTag.isPresent() && cTag.isPresent()) {
+ } else if (sTag.isPresent() && cTag.isPresent() && tpId.isPresent()) {
Port uplinkPort = getUplinkPort(deviceService.getDevice(subsPort.deviceId()));
if (uplinkPort == null) {
log.warn(NO_UPLINK_PORT, subsPort.deviceId());
return false;
}
- CompletableFuture<ObjectiveError> filterFuture = new CompletableFuture();
-
//delete Eapol authentication flow with default bandwidth
//wait until Eapol rule with defaultBpId is removed to install subscriber-based rules
- processEapolFilteringObjectives(subsPort.deviceId(), subsPort.port(), defaultBpId, filterFuture,
- VlanId.vlanId(EAPOL_DEFAULT_VLAN), false);
- // do not remove meter from bpInfoToMeter mapping as flows for other ONUs
- // could still be using it - this also prevents duplicate meters from being
- // created for the same bandwidth profile
- // we still need to remove from programmedMeters so the meter can be
- // deleted if its reference count drops to zero
- removeMeterIdFromPrgMeters(subsPort.deviceId(), defaultBpId);
-
//install subscriber flows
+ CompletableFuture<ObjectiveError> filterFuture = new CompletableFuture();
+ oltFlowService.processEapolFilteringObjectives(subsPort.deviceId(), subsPort.port(), defaultBpId,
+ filterFuture, VlanId.vlanId(EAPOL_DEFAULT_VLAN), false);
filterFuture.thenAcceptAsync(filterStatus -> {
if (filterStatus == null) {
- provisionTransparentFlows(subsPort.deviceId(), uplinkPort.number(), subsPort.port(),
- cTag.get(), sTag.get());
+ provisionUniTagInformation(subsPort.deviceId(), uplinkPort.number(), subsPort.port(),
+ cTag.get(), sTag.get(), tpId.get());
}
});
return true;
@@ -531,7 +334,8 @@
}
@Override
- public boolean removeSubscriber(AccessSubscriberId subscriberId, Optional<VlanId> sTag, Optional<VlanId> cTag) {
+ public boolean removeSubscriber(AccessSubscriberId subscriberId, Optional<VlanId> sTag,
+ Optional<VlanId> cTag, Optional<Integer> tpId) {
// Check if we can find the connect point to which this subscriber is connected
ConnectPoint subsPort = findSubscriberConnectPoint(subscriberId.toString());
if (subsPort == null) {
@@ -541,7 +345,7 @@
if (!sTag.isPresent() && !cTag.isPresent()) {
return removeSubscriber(subsPort);
- } else if (sTag.isPresent() && cTag.isPresent()) {
+ } else if (sTag.isPresent() && cTag.isPresent() && tpId.isPresent()) {
// Get the uplink port
Port uplinkPort = getUplinkPort(deviceService.getDevice(subsPort.deviceId()));
if (uplinkPort == null) {
@@ -549,60 +353,28 @@
return false;
}
- unprovisionTransparentFlows(subsPort.deviceId(), uplinkPort.number(), subsPort.port(),
- cTag.get(), sTag.get());
+ Optional<UniTagInformation> tagInfo = getUniTagInformation(subsPort, cTag.get(), sTag.get(), tpId.get());
+ if (!tagInfo.isPresent()) {
+ log.warn("UniTagInformation does not exist for Device/Port {}, cTag {}, sTag {}, tpId {}",
+ subsPort, cTag, sTag, tpId);
+ return false;
+ }
- programmedSubs.remove(subsPort);
-
+ unprovisionVlans(subsPort.deviceId(), uplinkPort.number(), subsPort.port(), tagInfo.get());
return true;
} else {
- log.warn("Removing subscriber failed for: {}", subscriberId);
+ log.warn("Removing subscriber is not possible - please check the provided information" +
+ "for the subscriber: {}", subscriberId);
return false;
}
}
@Override
- public Collection<Map.Entry<ConnectPoint, Map.Entry<VlanId, VlanId>>> getSubscribers() {
- ArrayList<Map.Entry<ConnectPoint, Map.Entry<VlanId, VlanId>>> subs = new ArrayList<>();
-
- // Get the subscribers for all the devices configured in sadis
- // If the port is UNI, is enabled and exists in Sadis then copy it
- for (Device d : deviceService.getDevices()) {
- if (getOltInfo(d) == null) {
- continue; // not an olt, or not configured in sadis
- }
- for (Port p : deviceService.getPorts(d.id())) {
- if (isUniPort(d, p) && p.isEnabled()) {
- ConnectPoint cp = new ConnectPoint(d.id(), p.number());
-
- SubscriberAndDeviceInformation sub = getSubscriber(cp);
- if (sub != null) {
- Map.Entry<VlanId, VlanId> vlans = new AbstractMap.SimpleEntry(sub.sTag(), sub.cTag());
- subs.add(new AbstractMap.SimpleEntry(cp, vlans));
- }
- }
- }
- }
-
- return subs;
- }
-
- @Override
- public ImmutableMap<ConnectPoint, SubscriberAndDeviceInformation> getProgSubs() {
+ public ImmutableMap<ConnectPoint, Set<UniTagInformation>> getProgSubs() {
return ImmutableMap.copyOf(programmedSubs);
}
@Override
- public ImmutableSet<MeterKey> getProgMeters() {
- return ImmutableSet.copyOf(programmedMeters);
- }
-
- @Override
- public ImmutableMap<String, List<MeterKey>> getBpMeterMappings() {
- return ImmutableMap.copyOf(bpInfoToMeter);
- }
-
- @Override
public List<DeviceId> fetchOlts() {
// look through all the devices and find the ones that are OLTs as per Sadis
List<DeviceId> olts = new ArrayList<>();
@@ -637,6 +409,12 @@
return null;
}
+ /**
+ * Gets the context of the bandwidth profile information for the given parameter.
+ *
+ * @param bandwidthProfile the bandwidth profile id
+ * @return the context of the bandwidth profile information
+ */
private BandwidthProfileInformation getBandwidthProfileInformation(String bandwidthProfile) {
if (bandwidthProfile == null) {
return null;
@@ -650,30 +428,37 @@
* @param deviceId the device identifier
* @param uplink uplink port of the OLT
* @param subscriberPort uni port
- * @param subscriber subscriber info that includes s, c tags, tech profile and bandwidth profile references
- * @param defaultVlan default vlan of the subscriber
+ * @param uniTag uni tag information
*/
private void unprovisionVlans(DeviceId deviceId, PortNumber uplink,
- PortNumber subscriberPort, SubscriberAndDeviceInformation subscriber,
- Optional<VlanId> defaultVlan) {
- log.info("Unprovisioning vlans for subscriber {} on dev/port: {}/{}",
- subscriber, deviceId, subscriberPort);
+ PortNumber subscriberPort, UniTagInformation uniTag) {
+
+ log.info("Unprovisioning vlans for {} at {}/{}", uniTag, deviceId, subscriberPort);
CompletableFuture<ObjectiveError> downFuture = new CompletableFuture();
CompletableFuture<ObjectiveError> upFuture = new CompletableFuture();
- VlanId deviceVlan = subscriber.sTag();
- VlanId subscriberVlan = subscriber.cTag();
+ VlanId deviceVlan = uniTag.getPonSTag();
+ VlanId subscriberVlan = uniTag.getPonCTag();
- MeterId upstreamMeterId = getMeterIdFromBpMapping(deviceId, subscriber.upstreamBandwidthProfile());
- MeterId downstreamMeterId = getMeterIdFromBpMapping(deviceId, subscriber.downstreamBandwidthProfile());
+ MeterId upstreamMeterId = oltMeterService
+ .getMeterIdFromBpMapping(deviceId, uniTag.getUpstreamBandwidthProfile());
+ MeterId downstreamMeterId = oltMeterService
+ .getMeterIdFromBpMapping(deviceId, uniTag.getDownstreamBandwidthProfile());
- ForwardingObjective.Builder upFwd = upBuilder(uplink, subscriberPort,
- subscriberVlan, deviceVlan,
- defaultVlan, upstreamMeterId, subscriber.technologyProfileId());
- ForwardingObjective.Builder downFwd = downBuilder(uplink, subscriberPort,
- subscriberVlan, deviceVlan,
- defaultVlan, downstreamMeterId, subscriber.technologyProfileId());
+ ForwardingObjective.Builder upFwd =
+ oltFlowService.createUpBuilder(uplink, subscriberPort, upstreamMeterId, uniTag);
+ ForwardingObjective.Builder downFwd =
+ oltFlowService.createDownBuilder(uplink, subscriberPort, downstreamMeterId, uniTag);
+
+ if (uniTag.getIsIgmpRequired()) {
+ oltFlowService.processIgmpFilteringObjectives(deviceId, subscriberPort,
+ upstreamMeterId, uniTag, false, true);
+ }
+ if (uniTag.getIsDhcpRequired()) {
+ oltFlowService.processDhcpFilteringObjectives(deviceId, subscriberPort,
+ upstreamMeterId, uniTag, false, true);
+ }
flowObjectiveService.forward(deviceId, upFwd.remove(new ObjectiveContext() {
@Override
@@ -700,317 +485,148 @@
}));
upFuture.thenAcceptBothAsync(downFuture, (upStatus, downStatus) -> {
+ AccessDeviceEvent.Type type = AccessDeviceEvent.Type.SUBSCRIBER_UNI_TAG_UNREGISTERED;
if (upStatus == null && downStatus == null) {
- post(new AccessDeviceEvent(AccessDeviceEvent.Type.SUBSCRIBER_UNREGISTERED,
- deviceId,
- deviceVlan,
- subscriberVlan));
+ log.debug("Uni tag information is unregistered successfully for cTag {}, sTag {}, tpId {}, and" +
+ "Device/Port{}", uniTag.getPonCTag(), uniTag.getPonSTag(),
+ uniTag.getTechnologyProfileId(), subscriberPort);
+ updateProgrammedSubscriber(new ConnectPoint(deviceId, subscriberPort), uniTag, false);
} else if (downStatus != null) {
log.error("Subscriber with vlan {} on device {} " +
- "on port {} failed downstream uninstallation: {}",
- subscriberVlan, deviceId, subscriberPort, downStatus);
+ "on port {} failed downstream uninstallation: {}",
+ subscriberVlan, deviceId, subscriberPort, downStatus);
+ type = AccessDeviceEvent.Type.SUBSCRIBER_UNI_TAG_UNREGISTRATION_FAILED;
} else if (upStatus != null) {
log.error("Subscriber with vlan {} on device {} " +
- "on port {} failed upstream uninstallation: {}",
- subscriberVlan, deviceId, subscriberPort, upStatus);
+ "on port {} failed upstream uninstallation: {}",
+ subscriberVlan, deviceId, subscriberPort, upStatus);
+ type = AccessDeviceEvent.Type.SUBSCRIBER_UNI_TAG_UNREGISTRATION_FAILED;
}
+ Port port = deviceService.getPort(deviceId, subscriberPort);
+ post(new AccessDeviceEvent(type, deviceId, port, deviceVlan, subscriberVlan,
+ uniTag.getTechnologyProfileId()));
}, oltInstallers);
-
- programmedMeters.remove(MeterKey.key(deviceId, upstreamMeterId));
- programmedMeters.remove(MeterKey.key(deviceId, downstreamMeterId));
- log.debug("programmed Meters size {}", programmedMeters.size());
}
/**
* Adds subscriber vlan flows, dhcp, eapol and igmp trap flows for the related uni port.
*
- * @param port the connection point of the subscriber
- * @param uplinkPort uplink port of the OLT
- * @param defaultVlan default vlan of the subscriber
- * @param sub subscriber information that includes s, c tags, tech profile and bandwidth profile references
+ * @param connectPoint the connection point of the subscriber
+ * @param uplinkPort uplink port of the OLT (the nni port)
+ * @param sub subscriber information that includes s, c tags, tech profile and bandwidth profile references
*/
- private void provisionSubscriberBasedFlows(ConnectPoint port, PortNumber uplinkPort,
- Optional<VlanId> defaultVlan,
- SubscriberAndDeviceInformation sub) {
+ private void provisionUniTagList(ConnectPoint connectPoint, PortNumber uplinkPort,
+ SubscriberAndDeviceInformation sub) {
- log.info("Provisioning vlans for subscriber {} on dev/port: {}",
- sub, port);
+ log.info("Provisioning vlans for subscriber {} on dev/port: {}", sub, connectPoint);
- DeviceId deviceId = port.deviceId();
- PortNumber subscriberPort = port.port();
- VlanId deviceVlan = sub.sTag();
- VlanId subscriberVlan = sub.cTag();
- int techProfId = sub.technologyProfileId();
+ if (sub.uniTagList() == null || sub.uniTagList().isEmpty()) {
+ log.warn("Unitaglist doesn't exist for the subscriber {}", sub.id());
+ return;
+ }
- BandwidthProfileInformation upstreamBpInfo = getBandwidthProfileInformation(sub.upstreamBandwidthProfile());
- BandwidthProfileInformation downstreamBpInfo = getBandwidthProfileInformation(sub.downstreamBandwidthProfile());
+ DeviceId deviceId = connectPoint.deviceId();
+ PortNumber subscriberPort = connectPoint.port();
- CompletableFuture<ObjectiveError> downFuture = new CompletableFuture();
- CompletableFuture<ObjectiveError> upFuture = new CompletableFuture();
- CompletableFuture<Object> upstreamMeterFuture = new CompletableFuture<>();
- CompletableFuture<Object> downsteamMeterFuture = new CompletableFuture<>();
+ for (UniTagInformation uniTag : sub.uniTagList()) {
+ handleSubscriberFlows(deviceId, uplinkPort, subscriberPort, uniTag);
+ }
+ }
- MeterId upstreamMeterId = createMeter(deviceId, upstreamBpInfo, upstreamMeterFuture);
- MeterId downstreamMeterId = createMeter(deviceId, downstreamBpInfo, downsteamMeterFuture);
+ /**
+ * Finds the uni tag information and provisions the found information.
+ * If the uni tag information is not found, returns
+ *
+ * @param deviceId the access device id
+ * @param uplinkPort the nni port
+ * @param subscriberPort the uni port
+ * @param innerVlan the pon c tag
+ * @param outerVlan the pon s tag
+ * @param tpId the technology profile id
+ */
+ private void provisionUniTagInformation(DeviceId deviceId, PortNumber uplinkPort,
+ PortNumber subscriberPort,
+ VlanId innerVlan,
+ VlanId outerVlan,
+ Integer tpId) {
- //install upstream flows
- upstreamMeterFuture.thenAcceptAsync(result -> {
- if (result == null) {
- log.info("Upstream Meter {} is in the device {}. " +
- "Sending subscriber flows.", upstreamMeterId, deviceId);
- ForwardingObjective.Builder upFwd = upBuilder(uplinkPort, subscriberPort,
- subscriberVlan, deviceVlan,
- defaultVlan, upstreamMeterId, techProfId);
+ ConnectPoint cp = new ConnectPoint(deviceId, subscriberPort);
+ Optional<UniTagInformation> gotTagInformation = getUniTagInformation(cp, innerVlan, outerVlan, tpId);
+ if (!gotTagInformation.isPresent()) {
+ return;
+ }
+ UniTagInformation tagInformation = gotTagInformation.get();
+ handleSubscriberFlows(deviceId, uplinkPort, subscriberPort, tagInformation);
+ }
-
- flowObjectiveService.forward(deviceId, upFwd.add(new ObjectiveContext() {
- @Override
- public void onSuccess(Objective objective) {
- upFuture.complete(null);
- }
-
- @Override
- public void onError(Objective objective, ObjectiveError error) {
- upFuture.complete(error);
- }
- }));
- } else {
- log.warn("Meter installation error while sending upstream flows. " +
- "Result {} and MeterId {}", result, upstreamMeterId);
- }
- });
-
- //install downstream flows
- downsteamMeterFuture.thenAcceptAsync(result -> {
- if (result == null) {
- log.info("Downstream Meter {} is in the device {}. " +
- "Sending subscriber flows.", downstreamMeterId, deviceId);
- ForwardingObjective.Builder downFwd = downBuilder(uplinkPort, subscriberPort,
- subscriberVlan, deviceVlan,
- defaultVlan, downstreamMeterId, techProfId);
-
- flowObjectiveService.forward(deviceId, downFwd.add(new ObjectiveContext() {
- @Override
- public void onSuccess(Objective objective) {
- downFuture.complete(null);
- }
-
- @Override
- public void onError(Objective objective, ObjectiveError error) {
- downFuture.complete(error);
- }
- }));
- } else {
- log.warn("Meter installation error while sending downstream flows. " +
- "Result {} and MeterId {}", result, downstreamMeterId);
- }
- });
-
- //send eapol & dhcp & igmp flows
- //send Subscriber Registered event
- upFuture.thenAcceptBothAsync(downFuture, (upStatus, downStatus) -> {
- if (upStatus == null && downStatus == null) {
-
- if (upstreamMeterId != null) {
- //re-install Eapol authentication flow with the subscribers' upstream bandwidth profile
- processEapolFilteringObjectives(deviceId, subscriberPort, sub.upstreamBandwidthProfile(),
- null, sub.cTag(), true);
-
- processDhcpFilteringObjectives(deviceId, subscriberPort,
- upstreamMeterId, sub.technologyProfileId(), true, true);
-
- processIgmpFilteringObjectives(deviceId, subscriberPort,
- upstreamMeterId, sub.technologyProfileId(), true);
+ private void updateProgrammedSubscriber(ConnectPoint connectPoint, UniTagInformation tagInformation, Boolean add) {
+ programmedSubs.compute(connectPoint, (k, v) -> {
+ if (add) {
+ if (v == null) {
+ v = Sets.newHashSet();
}
-
- post(new AccessDeviceEvent(AccessDeviceEvent.Type.SUBSCRIBER_REGISTERED,
- deviceId,
- deviceVlan,
- subscriberVlan));
-
- } else if (downStatus != null) {
- log.error("Subscriber with vlan {} on device {} " +
- "on port {} failed downstream installation: {}",
- subscriberVlan, deviceId, subscriberPort, downStatus);
- } else if (upStatus != null) {
- log.error("Subscriber with vlan {} on device {} " +
- "on port {} failed upstream installation: {}",
- subscriberVlan, deviceId, subscriberPort, upStatus);
+ v.add(tagInformation);
+ } else {
+ if (v != null) {
+ v.remove(tagInformation);
+ }
}
- }, oltInstallers);
+ return v;
+ });
}
- private MeterId createMeter(DeviceId deviceId, BandwidthProfileInformation bpInfo,
- CompletableFuture<Object> meterFuture) {
- if (bpInfo == null) {
- log.warn("Bandwidth profile information cannot be null when creating meter");
- return null;
+ /**
+ * Installs a uni tag information flow.
+ *
+ * @param deviceId the access device id
+ * @param uplinkPort the nni port
+ * @param subscriberPort the uni port
+ * @param tagInfo the uni tag information
+ */
+ private void handleSubscriberFlows(DeviceId deviceId, PortNumber uplinkPort, PortNumber subscriberPort,
+ UniTagInformation tagInfo) {
+
+ log.info("Provisioning vlan-based flows for the uniTagInformation {}", tagInfo);
+
+ Port port = deviceService.getPort(deviceId, subscriberPort);
+
+ if (multicastServiceName.equals(tagInfo.getServiceName())) {
+ // IGMP flows are taken care of along with VOD service
+ // Please note that for each service, Subscriber Registered event will be sent
+ post(new AccessDeviceEvent(AccessDeviceEvent.Type.SUBSCRIBER_UNI_TAG_REGISTERED,
+ deviceId, port, tagInfo.getPonSTag(), tagInfo.getPonCTag(),
+ tagInfo.getTechnologyProfileId()));
+ return;
}
- MeterId meterId = getMeterIdFromBpMapping(deviceId, bpInfo.id());
- if (meterId != null) {
- log.debug("Meter {} was previously created for bp {}", meterId,
- bpInfo.id());
- meterFuture.complete(null);
- return meterId;
- }
-
- List<Band> meterBands = createMeterBands(bpInfo);
-
- MeterRequest meterRequest = DefaultMeterRequest.builder()
- .withBands(meterBands)
- .withUnit(Meter.Unit.KB_PER_SEC)
- .withContext(new MeterContext() {
- @Override
- public void onSuccess(MeterRequest op) {
- log.debug("meter addition confirmed for bpInfo:{}", bpInfo);
- meterFuture.complete(null);
- }
-
- @Override
- public void onError(MeterRequest op, MeterFailReason reason) {
- meterFuture.complete(reason);
- }
- })
- .forDevice(deviceId)
- .fromApp(appId)
- .burst()
- .add();
-
- Meter meter = meterService.submit(meterRequest);
- addMeterIdToBpMapping(deviceId, meter.id(), bpInfo.id());
- log.info("Meter creation message sent for Meter Id {}", meter.id());
- programmedMeters.add(MeterKey.key(deviceId, meter.id()));
- return meter.id();
- }
-
- private List<Band> createMeterBands(BandwidthProfileInformation bpInfo) {
- List<Band> meterBands = new ArrayList<>();
-
- meterBands.add(createMeterBand(bpInfo.committedInformationRate(), bpInfo.committedBurstSize()));
- meterBands.add(createMeterBand(bpInfo.exceededInformationRate(), bpInfo.exceededBurstSize()));
- meterBands.add(createMeterBand(bpInfo.assuredInformationRate(), 0L));
-
- return meterBands;
- }
-
- private Band createMeterBand(long rate, Long burst) {
- return DefaultBand.builder()
- .withRate(rate) //already Kbps
- .burstSize(burst) // already Kbits
- .ofType(Band.Type.DROP) // no matter
- .build();
- }
-
- private ForwardingObjective.Builder downBuilder(PortNumber uplinkPort,
- PortNumber subscriberPort,
- VlanId subscriberVlan,
- VlanId deviceVlan,
- Optional<VlanId> defaultVlan,
- MeterId meterId,
- int techProfId) {
- TrafficSelector downstream = DefaultTrafficSelector.builder()
- .matchVlanId(deviceVlan)
- .matchInPort(uplinkPort)
- .matchInnerVlanId(subscriberVlan)
- .build();
-
- TrafficTreatment.Builder downstreamTreatmentBuilder = DefaultTrafficTreatment.builder()
- .popVlan()
- .setVlanId(defaultVlan.orElse(VlanId.vlanId((short) this.defaultVlan)))
- .setOutput(subscriberPort);
-
- if (meterId != null) {
- downstreamTreatmentBuilder.meter(meterId);
- }
-
- downstreamTreatmentBuilder.writeMetadata(createMetadata(subscriberVlan, techProfId, subscriberPort), 0);
-
- return DefaultForwardingObjective.builder()
- .withFlag(ForwardingObjective.Flag.VERSATILE)
- .withPriority(1000)
- .makePermanent()
- .withSelector(downstream)
- .fromApp(appId)
- .withTreatment(downstreamTreatmentBuilder.build());
- }
-
- private ForwardingObjective.Builder upBuilder(PortNumber uplinkPort,
- PortNumber subscriberPort,
- VlanId subscriberVlan,
- VlanId deviceVlan,
- Optional<VlanId> defaultVlan,
- MeterId meterId,
- int technologyProfileId) {
-
-
- VlanId dVlan = defaultVlan.orElse(VlanId.vlanId((short) this.defaultVlan));
-
- if (subscriberVlan.toShort() == 4096) {
- dVlan = subscriberVlan;
- }
-
- TrafficSelector upstream = DefaultTrafficSelector.builder()
- .matchVlanId(dVlan)
- .matchInPort(subscriberPort)
- .build();
-
-
- TrafficTreatment.Builder upstreamTreatmentBuilder = DefaultTrafficTreatment.builder()
- .pushVlan()
- .setVlanId(subscriberVlan)
- .pushVlan()
- .setVlanId(deviceVlan)
- .setOutput(uplinkPort);
-
- if (meterId != null) {
- upstreamTreatmentBuilder.meter(meterId);
- }
-
- upstreamTreatmentBuilder.writeMetadata(createMetadata(deviceVlan, technologyProfileId, uplinkPort), 0L);
-
- return DefaultForwardingObjective.builder()
- .withFlag(ForwardingObjective.Flag.VERSATILE)
- .withPriority(1000)
- .makePermanent()
- .withSelector(upstream)
- .fromApp(appId)
- .withTreatment(upstreamTreatmentBuilder.build());
- }
-
- private void provisionTransparentFlows(DeviceId deviceId, PortNumber uplinkPort,
- PortNumber subscriberPort,
- VlanId innerVlan,
- VlanId outerVlan) {
-
ConnectPoint cp = new ConnectPoint(deviceId, subscriberPort);
- SubscriberAndDeviceInformation subInfo = getSubscriber(cp);
-
- BandwidthProfileInformation upstreamBpInfo = getBandwidthProfileInformation(
- subInfo.upstreamBandwidthProfile());
- BandwidthProfileInformation downstreamBpInfo = getBandwidthProfileInformation(
- subInfo.downstreamBandwidthProfile());
+ BandwidthProfileInformation upstreamBpInfo =
+ getBandwidthProfileInformation(tagInfo.getUpstreamBandwidthProfile());
+ BandwidthProfileInformation downstreamBpInfo =
+ getBandwidthProfileInformation(tagInfo.getDownstreamBandwidthProfile());
CompletableFuture<Object> upstreamMeterFuture = new CompletableFuture<>();
CompletableFuture<Object> downsteamMeterFuture = new CompletableFuture<>();
- CompletableFuture<ObjectiveError> upFuture = new CompletableFuture();
- CompletableFuture<ObjectiveError> downFuture = new CompletableFuture();
+ CompletableFuture<ObjectiveError> upFuture = new CompletableFuture<>();
+ CompletableFuture<ObjectiveError> downFuture = new CompletableFuture<>();
- MeterId upstreamMeterId = createMeter(deviceId, upstreamBpInfo, upstreamMeterFuture);
- MeterId downstreamMeterId = createMeter(deviceId, downstreamBpInfo, downsteamMeterFuture);
+ MeterId upstreamMeterId = oltMeterService.createMeter(deviceId, upstreamBpInfo, upstreamMeterFuture);
+
+ MeterId downstreamMeterId = oltMeterService.createMeter(deviceId, downstreamBpInfo, downsteamMeterFuture);
upstreamMeterFuture.thenAcceptAsync(result -> {
if (result == null) {
log.info("Upstream Meter {} is sent to the device {}. " +
- "Sending subscriber flows.", upstreamMeterId, deviceId);
+ "Sending subscriber flows.", upstreamMeterId, deviceId);
- ForwardingObjective.Builder upFwd = transparentUpBuilder(uplinkPort, subscriberPort,
- innerVlan, outerVlan, upstreamMeterId, subInfo);
+ ForwardingObjective.Builder upFwd =
+ oltFlowService.createUpBuilder(uplinkPort, subscriberPort, upstreamMeterId, tagInfo);
flowObjectiveService.forward(deviceId, upFwd.add(new ObjectiveContext() {
@Override
public void onSuccess(Objective objective) {
+ log.info("Upstream flow installed successfully");
upFuture.complete(null);
}
@@ -1020,23 +636,30 @@
}
}));
+ } else if (upstreamBpInfo == null) {
+ log.warn("No meter installed since no Upstream BW Profile definition found for " +
+ "ctag {} stag {} tpId {} and Device/port: {}:{}",
+ tagInfo.getPonCTag(), tagInfo.getPonSTag(),
+ tagInfo.getTechnologyProfileId(),
+ deviceId, subscriberPort);
} else {
log.warn("Meter installation error while sending upstream flows. " +
- "Result {} and MeterId {}", result, upstreamMeterId);
+ "Result {} and MeterId {}", result, upstreamMeterId);
}
});
downsteamMeterFuture.thenAcceptAsync(result -> {
if (result == null) {
log.info("Downstream Meter {} is sent to the device {}. " +
- "Sending subscriber flows.", downstreamMeterId, deviceId);
+ "Sending subscriber flows.", downstreamMeterId, deviceId);
- ForwardingObjective.Builder downFwd = transparentDownBuilder(uplinkPort, subscriberPort,
- innerVlan, outerVlan, downstreamMeterId, subInfo);
+ ForwardingObjective.Builder downFwd =
+ oltFlowService.createDownBuilder(uplinkPort, subscriberPort, downstreamMeterId, tagInfo);
flowObjectiveService.forward(deviceId, downFwd.add(new ObjectiveContext() {
@Override
public void onSuccess(Objective objective) {
+ log.info("Downstream flow installed successfully");
downFuture.complete(null);
}
@@ -1045,500 +668,95 @@
downFuture.complete(error);
}
}));
+
+ } else if (downstreamBpInfo == null) {
+ log.warn("No meter installed since no Downstream BW Profile definition found for " +
+ "ctag {} stag {} tpId {} and Device/port: {}:{}",
+ tagInfo.getPonCTag(), tagInfo.getPonSTag(),
+ tagInfo.getTechnologyProfileId(),
+ deviceId, subscriberPort);
} else {
log.warn("Meter installation error while sending upstream flows. " +
- "Result {} and MeterId {}", result, downstreamMeterId);
+ "Result {} and MeterId {}", result, downstreamMeterId);
}
});
- additionalVlans.put(cp, new AbstractMap.SimpleEntry(outerVlan, innerVlan));
-
upFuture.thenAcceptBothAsync(downFuture, (upStatus, downStatus) -> {
+ AccessDeviceEvent.Type type = AccessDeviceEvent.Type.SUBSCRIBER_UNI_TAG_REGISTERED;
if (downStatus != null) {
log.error("Flow with innervlan {} and outerVlan {} on device {} " +
- "on port {} failed downstream installation: {}",
- innerVlan, outerVlan, deviceId, cp, downStatus);
+ "on port {} failed downstream installation: {}",
+ tagInfo.getPonCTag(), tagInfo.getPonSTag(), deviceId, cp, downStatus);
+ type = AccessDeviceEvent.Type.SUBSCRIBER_UNI_TAG_REGISTRATION_FAILED;
} else if (upStatus != null) {
log.error("Flow with innerVlan {} and outerVlan {} on device {} " +
- "on port {} failed upstream installation: {}",
- innerVlan, outerVlan, deviceId, cp, upStatus);
+ "on port {} failed upstream installation: {}",
+ tagInfo.getPonCTag(), tagInfo.getPonSTag(), deviceId, cp, upStatus);
+ type = AccessDeviceEvent.Type.SUBSCRIBER_UNI_TAG_REGISTRATION_FAILED;
} else {
- processEapolFilteringObjectives(deviceId, subscriberPort, subInfo.upstreamBandwidthProfile(),
- null, subInfo.cTag(), true);
+ log.info("Upstream and downstream data plane flows are installed successfully.");
+ oltFlowService.processEapolFilteringObjectives(deviceId, subscriberPort,
+ tagInfo.getUpstreamBandwidthProfile(),
+ null, tagInfo.getPonCTag(), true);
+ if (tagInfo.getIsDhcpRequired()) {
+ oltFlowService.processDhcpFilteringObjectives(deviceId, subscriberPort,
+ upstreamMeterId, tagInfo, true, true);
+ }
- // cache subscriber info
- programmedSubs.put(cp, subInfo);
+ if (tagInfo.getIsIgmpRequired()) {
+ oltFlowService.processIgmpFilteringObjectives(deviceId, subscriberPort, upstreamMeterId, tagInfo,
+ true, true);
+ }
+ updateProgrammedSubscriber(cp, tagInfo, true);
+ post(new AccessDeviceEvent(type, deviceId, port, tagInfo.getPonSTag(), tagInfo.getPonCTag(),
+ tagInfo.getTechnologyProfileId()));
}
}, oltInstallers);
-
}
- private ForwardingObjective.Builder transparentDownBuilder(PortNumber uplinkPort,
- PortNumber subscriberPort,
- VlanId innerVlan,
- VlanId outerVlan,
- MeterId downstreamMeterId,
- SubscriberAndDeviceInformation subInfo) {
- TrafficSelector downstream = DefaultTrafficSelector.builder()
- .matchVlanId(outerVlan)
- .matchInPort(uplinkPort)
- .matchInnerVlanId(innerVlan)
- .build();
-
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
- if (downstreamMeterId != null) {
- tBuilder.meter(downstreamMeterId);
- }
-
- TrafficTreatment downstreamTreatment = tBuilder
- .setOutput(subscriberPort)
- .writeMetadata(createMetadata(subInfo.cTag(), subInfo.technologyProfileId(), subscriberPort), 0)
- .build();
-
- return DefaultForwardingObjective.builder()
- .withFlag(ForwardingObjective.Flag.VERSATILE)
- .withPriority(1000)
- .makePermanent()
- .withSelector(downstream)
- .fromApp(appId)
- .withTreatment(downstreamTreatment);
- }
-
- private ForwardingObjective.Builder transparentUpBuilder(PortNumber uplinkPort,
- PortNumber subscriberPort,
- VlanId innerVlan,
- VlanId outerVlan,
- MeterId upstreamMeterId,
- SubscriberAndDeviceInformation subInfo) {
-
- TrafficSelector upstream = DefaultTrafficSelector.builder()
- .matchVlanId(outerVlan)
- .matchInPort(subscriberPort)
- .matchInnerVlanId(innerVlan)
- .build();
-
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
- if (upstreamMeterId != null) {
- tBuilder.meter(upstreamMeterId);
- }
-
- TrafficTreatment upstreamTreatment = tBuilder
- .setOutput(uplinkPort)
- .writeMetadata(createMetadata(subInfo.sTag(), subInfo.technologyProfileId(), uplinkPort), 0)
- .build();
-
- return DefaultForwardingObjective.builder()
- .withFlag(ForwardingObjective.Flag.VERSATILE)
- .withPriority(1000)
- .makePermanent()
- .withSelector(upstream)
- .fromApp(appId)
- .withTreatment(upstreamTreatment);
- }
-
- private void unprovisionTransparentFlows(DeviceId deviceId, PortNumber uplink,
- PortNumber subscriberPort, VlanId innerVlan,
- VlanId outerVlan) {
-
- ConnectPoint cp = new ConnectPoint(deviceId, subscriberPort);
-
- SubscriberAndDeviceInformation subInfo = programmedSubs.get(cp);
+ /**
+ * Checks the subscriber uni tag list and find the uni tag information.
+ * using the pon c tag, pon s tag and the technology profile id
+ * May return Optional<null>
+ *
+ * @param cp the connection point of the subscriber
+ * @param innerVlan pon c tag
+ * @param outerVlan pon s tag
+ * @param tpId the technology profile id
+ * @return the found uni tag information
+ */
+ private Optional<UniTagInformation> getUniTagInformation(ConnectPoint cp, VlanId innerVlan, VlanId outerVlan,
+ int tpId) {
+ log.info("Getting uni tag information for cp: {}, innerVlan: {}, outerVlan: {}, tpId: {}", cp, innerVlan,
+ outerVlan, tpId);
+ SubscriberAndDeviceInformation subInfo = getSubscriber(cp);
if (subInfo == null) {
- log.warn("Subscriber is not programmed before for the connectPoint {}", cp);
- return;
+ log.warn("Subscriber information doesn't exist for the connect point {}", cp);
+ return Optional.empty();
}
- additionalVlans.remove(cp, new AbstractMap.SimpleEntry(outerVlan, innerVlan));
+ List<UniTagInformation> uniTagList = subInfo.uniTagList();
+ if (uniTagList == null) {
+ log.warn("Uni tag list is not found for the subscriber {}", subInfo.id());
+ return Optional.empty();
+ }
- CompletableFuture<ObjectiveError> downFuture = new CompletableFuture();
- CompletableFuture<ObjectiveError> upFuture = new CompletableFuture();
-
- MeterId upstreamMeterId = getMeterIdFromBpMapping(deviceId, subInfo.upstreamBandwidthProfile());
- MeterId downstreamMeterId = getMeterIdFromBpMapping(deviceId, subInfo.downstreamBandwidthProfile());
-
- ForwardingObjective.Builder upFwd = transparentUpBuilder(uplink, subscriberPort,
- innerVlan, outerVlan, upstreamMeterId, subInfo);
- ForwardingObjective.Builder downFwd = transparentDownBuilder(uplink, subscriberPort,
- innerVlan, outerVlan, downstreamMeterId, subInfo);
-
- flowObjectiveService.forward(deviceId, upFwd.remove(new ObjectiveContext() {
- @Override
- public void onSuccess(Objective objective) {
- upFuture.complete(null);
- }
-
- @Override
- public void onError(Objective objective, ObjectiveError error) {
- upFuture.complete(error);
- }
- }));
-
- flowObjectiveService.forward(deviceId, downFwd.remove(new ObjectiveContext() {
- @Override
- public void onSuccess(Objective objective) {
- downFuture.complete(null);
- }
-
- @Override
- public void onError(Objective objective, ObjectiveError error) {
- downFuture.complete(error);
- }
- }));
-
- upFuture.thenAcceptBothAsync(downFuture, (upStatus, downStatus) -> {
- if (downStatus != null) {
- log.error("Flow with innerVlan {} and outerVlan {} on device {} " +
- "on port {} failed downstream uninstallation: {}",
- innerVlan, outerVlan, deviceId, subscriberPort, downStatus);
- } else if (upStatus != null) {
- log.error("Flow with innerVlan {} and outerVlan {} on device {} " +
- "on port {} failed upstream uninstallation: {}",
- innerVlan, outerVlan, deviceId, subscriberPort, upStatus);
- }
- }, oltInstallers);
-
- //re-install eapol
- processEapolFilteringObjectives(deviceId, subscriberPort,
- subInfo.upstreamBandwidthProfile(), null, subInfo.cTag(), false);
- processEapolFilteringObjectives(deviceId, subscriberPort, defaultBpId,
- null, VlanId.vlanId(EAPOL_DEFAULT_VLAN), true);
-
- programmedMeters.remove(MeterKey.key(deviceId, upstreamMeterId));
- programmedMeters.remove(MeterKey.key(deviceId, downstreamMeterId));
- }
-
- private int getDefaultTechProfileId(DeviceId devId, PortNumber portNumber) {
- Port port = deviceService.getPort(devId, portNumber);
- if (port != null) {
- SubscriberAndDeviceInformation info = subsService.get(port.annotations().value(AnnotationKeys.PORT_NAME));
- if (info != null && info.technologyProfileId() != -1) {
- return info.technologyProfileId();
+ UniTagInformation service = null;
+ for (UniTagInformation tagInfo : subInfo.uniTagList()) {
+ if (innerVlan.equals(tagInfo.getPonCTag()) && outerVlan.equals(tagInfo.getPonSTag())
+ && tpId == tagInfo.getTechnologyProfileId()) {
+ service = tagInfo;
+ break;
}
}
- return defaultTechProfileId;
- }
- /**
- * Returns the write metadata value including tech profile reference and innerVlan.
- * For param cVlan, null can be sent
- *
- * @param cVlan c (customer) tag of one subscriber
- * @param techProfileId tech profile id of one subscriber
- * @return the write metadata value including tech profile reference and innerVlan
- */
- private Long createTechProfValueForWm(VlanId cVlan, int techProfileId) {
- if (cVlan == null) {
- return (long) techProfileId << 32;
- }
- return ((long) (cVlan.id()) << 48 | (long) techProfileId << 32);
- }
-
- /**
- * Trap eapol authentication packets to the controller.
- *
- * @param devId the device identifier
- * @param portNumber the port for which this trap flow is designated
- * @param bpId bandwidth profile id to add the related meter to the flow
- * @param filterFuture completable future for this filtering objective operation
- * @param vlanId the default or customer tag for a subscriber
- * @param install true to install the flow, false to remove the flow
- */
- private void processEapolFilteringObjectives(DeviceId devId, PortNumber portNumber, String bpId,
- CompletableFuture<ObjectiveError> filterFuture,
- VlanId vlanId, boolean install) {
- if (!enableEapol) {
- log.debug("Eapol filtering is disabled.");
- if (filterFuture != null) {
- filterFuture.complete(null);
- }
- return;
+ if (service == null) {
+ log.warn("SADIS doesn't include the service with ponCtag {} ponStag {} and tpId {}",
+ innerVlan, outerVlan, tpId);
+ return Optional.empty();
}
- if (!mastershipService.isLocalMaster(devId)) {
- return;
- }
- DefaultFilteringObjective.Builder builder = DefaultFilteringObjective.builder();
- TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
- CompletableFuture<Object> meterFuture = new CompletableFuture<>();
-
- BandwidthProfileInformation bpInfo = getBandwidthProfileInformation(bpId);
- if (bpInfo == null) {
- log.warn("Bandwidth profile {} is not found. Authentication flow"
- + " will not be installed", bpId);
- return;
- }
-
- // check if meter exists and create it only for an install
- MeterId meterId = getMeterIdFromBpMapping(devId, bpInfo.id());
- if (meterId == null) {
- if (install) {
- meterId = createMeter(devId, bpInfo, meterFuture);
- treatmentBuilder.meter(meterId);
- } else {
- // this case should not happen as the request to remove an eapol
- // flow should mean that the flow points to a meter that exists.
- // Nevertheless we can still delete the flow as we only need the
- // correct 'match' to do so.
- log.warn("Unknown meter id for bp {}, still proceeding with "
- + "delete of eapol flow for {}/{}", bpInfo.id(), devId,
- portNumber);
- meterFuture.complete(null);
- }
- } else {
- log.debug("Meter {} was previously created for bp {}", meterId,
- bpInfo.id());
- treatmentBuilder.meter(meterId);
- meterFuture.complete(null);
- }
-
- final MeterId mId = meterId;
- meterFuture.thenAcceptAsync(result -> {
- if (result == null) {
- log.info("Meter {} for {} on {}/{} exists. {} EAPOL trap flow",
- mId, bpId, devId, portNumber,
- (install) ? "Installing " : "Removing ");
- int techProfileId = getDefaultTechProfileId(devId, portNumber);
-
- //Authentication trap flow uses only tech profile id as write metadata value
- FilteringObjective eapol = (install ? builder.permit() : builder.deny())
- .withKey(Criteria.matchInPort(portNumber))
- .addCondition(Criteria.matchEthType(EthType.EtherType.EAPOL.ethType()))
- .addCondition(Criteria.matchVlanId(vlanId))
- .withMeta(treatmentBuilder
- .writeMetadata(createTechProfValueForWm(vlanId, techProfileId), 0)
- .setOutput(PortNumber.CONTROLLER).build())
- .fromApp(appId)
- .withPriority(10000)
- .add(new ObjectiveContext() {
- @Override
- public void onSuccess(Objective objective) {
- log.info("Eapol filter for {} on {} {} with meter {}.",
- devId, portNumber, (install) ? INSTALLED : REMOVED, mId);
- if (filterFuture != null) {
- filterFuture.complete(null);
- }
- }
-
- @Override
- public void onError(Objective objective, ObjectiveError error) {
- log.info("Eapol filter for {} on {} with meter {} failed {} because {}",
- devId, portNumber, mId, (install) ? INSTALLATION : REMOVAL,
- error);
- if (filterFuture != null) {
- filterFuture.complete(error);
- }
- }
- });
-
- flowObjectiveService.filter(devId, eapol);
- } else {
- log.warn("Meter installation error while sending eapol trap flow. " +
- "Result {} and MeterId {}", result, mId);
- }
- });
- }
-
- /**
- * Installs trap filtering objectives for particular traffic types on an
- * NNI port.
- *
- * @param devId device ID
- * @param port port number
- * @param install true to install, false to remove
- */
- private void processNniFilteringObjectives(DeviceId devId, PortNumber port, boolean install) {
- processLldpFilteringObjective(devId, port, install);
- processDhcpFilteringObjectives(devId, port, null, -1, install, false);
- }
-
- private void processLldpFilteringObjective(DeviceId devId, PortNumber port, boolean install) {
- if (!mastershipService.isLocalMaster(devId)) {
- return;
- }
- DefaultFilteringObjective.Builder builder = DefaultFilteringObjective.builder();
-
- FilteringObjective lldp = (install ? builder.permit() : builder.deny())
- .withKey(Criteria.matchInPort(port))
- .addCondition(Criteria.matchEthType(EthType.EtherType.LLDP.ethType()))
- .withMeta(DefaultTrafficTreatment.builder()
- .setOutput(PortNumber.CONTROLLER).build())
- .fromApp(appId)
- .withPriority(10000)
- .add(new ObjectiveContext() {
- @Override
- public void onSuccess(Objective objective) {
- log.info("LLDP filter for device {} on port {} {}.",
- devId, port, (install) ? INSTALLED : REMOVED);
- }
-
- @Override
- public void onError(Objective objective, ObjectiveError error) {
- log.info("LLDP filter for device {} on port {} failed {} because {}",
- devId, port, (install) ? INSTALLATION : REMOVAL,
- error);
- }
- });
-
- flowObjectiveService.filter(devId, lldp);
-
- }
-
- /**
- * Trap dhcp packets to the controller.
- *
- * @param devId the device identifier
- * @param port the port for which this trap flow is designated
- * @param upstreamMeterId the upstream meter id that includes the upstream
- * bandwidth profile values such as PIR,CIR. If no meter id needs to be referenced,
- * null can be sent
- * @param techProfileId the technology profile id that is used to create write
- * metadata instruction value. If no tech profile id needs to be referenced,
- * -1 can be sent
- * @param install true to install the flow, false to remove the flow
- * @param upstream true if trapped packets are flowing upstream towards
- * server, false if packets are flowing downstream towards client
- */
- private void processDhcpFilteringObjectives(DeviceId devId, PortNumber port,
- MeterId upstreamMeterId,
- int techProfileId,
- boolean install,
- boolean upstream) {
-
- if (!enableDhcpOnProvisioning) {
- log.debug("Dhcp provisioning is disabled.");
- return;
- }
-
- if (!mastershipService.isLocalMaster(devId)) {
- return;
- }
-
- if (enableDhcpV4) {
- int udpSrc = (upstream) ? 68 : 67;
- int udpDst = (upstream) ? 67 : 68;
-
- EthType ethType = EthType.EtherType.IPV4.ethType();
- byte protocol = IPv4.PROTOCOL_UDP;
-
- this.addDhcpFilteringObjectives(devId, port, udpSrc, udpDst, ethType,
- upstreamMeterId, techProfileId, protocol, install);
- }
-
- if (enableDhcpV6) {
- int udpSrc = (upstream) ? 547 : 546;
- int udpDst = (upstream) ? 546 : 547;
-
- EthType ethType = EthType.EtherType.IPV6.ethType();
- byte protocol = IPv6.PROTOCOL_UDP;
-
- this.addDhcpFilteringObjectives(devId, port, udpSrc, udpDst, ethType,
- upstreamMeterId, techProfileId, protocol, install);
- }
-
- }
-
- private void addDhcpFilteringObjectives(DeviceId devId,
- PortNumber port,
- int udpSrc,
- int udpDst,
- EthType ethType,
- MeterId upstreamMeterId,
- int techProfileId,
- byte protocol,
- boolean install) {
-
- DefaultFilteringObjective.Builder builder = DefaultFilteringObjective.builder();
- TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
-
- if (upstreamMeterId != null) {
- treatmentBuilder.meter(upstreamMeterId);
- }
-
- if (techProfileId != -1) {
- treatmentBuilder.writeMetadata(createTechProfValueForWm(null, techProfileId), 0);
- }
-
- FilteringObjective dhcpUpstream = (install ? builder.permit() : builder.deny())
- .withKey(Criteria.matchInPort(port))
- .addCondition(Criteria.matchEthType(ethType))
- .addCondition(Criteria.matchIPProtocol(protocol))
- .addCondition(Criteria.matchUdpSrc(TpPort.tpPort(udpSrc)))
- .addCondition(Criteria.matchUdpDst(TpPort.tpPort(udpDst)))
- .withMeta(treatmentBuilder
- .setOutput(PortNumber.CONTROLLER).build())
- .fromApp(appId)
- .withPriority(10000)
- .add(new ObjectiveContext() {
- @Override
- public void onSuccess(Objective objective) {
- log.info("DHCP {} filter for device {} on port {} {}.",
- (ethType.equals(EthType.EtherType.IPV4.ethType())) ? "v4" : "v6",
- devId, port, (install) ? INSTALLED : REMOVED);
- }
-
- @Override
- public void onError(Objective objective, ObjectiveError error) {
- log.info("DHCP {} filter for device {} on port {} failed {} because {}",
- (ethType.equals(EthType.EtherType.IPV4.ethType())) ? "v4" : "v6",
- devId, port, (install) ? INSTALLATION : REMOVAL,
- error);
- }
- });
-
- flowObjectiveService.filter(devId, dhcpUpstream);
- }
-
- private void processIgmpFilteringObjectives(DeviceId devId, PortNumber port,
- MeterId upstreamMeterId,
- int techProfileId,
- boolean install) {
-
- if (!enableIgmpOnProvisioning) {
- log.debug("Igmp provisioning is disabled.");
- return;
- }
-
- if (!mastershipService.isLocalMaster(devId)) {
- return;
- }
-
- DefaultFilteringObjective.Builder builder = DefaultFilteringObjective.builder();
- TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
-
- if (upstreamMeterId != null) {
- treatmentBuilder.meter(upstreamMeterId);
- }
-
- if (techProfileId != -1) {
- treatmentBuilder.writeMetadata(createTechProfValueForWm(null, techProfileId), 0);
- }
-
- builder = install ? builder.permit() : builder.deny();
-
- FilteringObjective igmp = builder
- .withKey(Criteria.matchInPort(port))
- .addCondition(Criteria.matchEthType(EthType.EtherType.IPV4.ethType()))
- .addCondition(Criteria.matchIPProtocol(IPv4.PROTOCOL_IGMP))
- .withMeta(treatmentBuilder
- .setOutput(PortNumber.CONTROLLER).build())
- .fromApp(appId)
- .withPriority(10000)
- .add(new ObjectiveContext() {
- @Override
- public void onSuccess(Objective objective) {
- log.info("Igmp filter for {} on {} {}.",
- devId, port, (install) ? INSTALLED : REMOVED);
- }
-
- @Override
- public void onError(Objective objective, ObjectiveError error) {
- log.info("Igmp filter for {} on {} failed {} because {}.",
- devId, port, (install) ? INSTALLATION : REMOVAL,
- error);
- }
- });
-
- flowObjectiveService.filter(devId, igmp);
+ return Optional.of(service);
}
/**
@@ -1554,16 +772,20 @@
}
// check if this device is provisioned in Sadis
SubscriberAndDeviceInformation deviceInfo = getOltInfo(dev);
- log.debug("checkAndCreateDeviceFlows: deviceInfo {}", deviceInfo);
+ log.info("checkAndCreateDeviceFlows: deviceInfo {}", deviceInfo);
if (deviceInfo != null) {
// This is an OLT device as per Sadis, we create flows for UNI and NNI ports
for (Port p : deviceService.getPorts(dev.id())) {
+ if (PortNumber.LOCAL.equals(p.number())) {
+ continue;
+ }
if (isUniPort(dev, p)) {
- processEapolFilteringObjectives(dev.id(), p.number(), defaultBpId, null,
- VlanId.vlanId(EAPOL_DEFAULT_VLAN), true);
+ log.info("Creating Eapol for the uni {}", p);
+ oltFlowService.processEapolFilteringObjectives(dev.id(), p.number(), defaultBpId, null,
+ VlanId.vlanId(EAPOL_DEFAULT_VLAN), true);
} else {
- processNniFilteringObjectives(dev.id(), p.number(), true);
+ oltFlowService.processNniFilteringObjectives(dev.id(), p.number(), true);
}
}
}
@@ -1585,7 +807,7 @@
log.trace("getUplinkPort: deviceInfo {}", deviceInfo);
if (deviceInfo == null) {
log.warn("Device {} is not configured in SADIS .. cannot fetch device"
- + " info", dev.id());
+ + " info", dev.id());
return null;
}
// Return the port that has been configured as the uplink port of this OLT in Sadis
@@ -1614,22 +836,12 @@
}
/**
- * Write metadata instruction value (metadata) is 8 bytes.
- * <p>
- * MS 2 bytes: C Tag
- * Next 2 bytes: Technology Profile Id
- * Next 4 bytes: Port number (uni or nni)
+ * Checks whether the given port of the device is a uni port or not.
+ *
+ * @param d the access device
+ * @param p the port of the device
+ * @return true if the given port is a uni port
*/
-
- private Long createMetadata(VlanId innerVlan, int techProfileId, PortNumber egressPort) {
-
- if (techProfileId == -1) {
- techProfileId = defaultTechProfileId;
- }
-
- return ((long) (innerVlan.id()) << 48 | (long) techProfileId << 32) | egressPort.toLong();
- }
-
private boolean isUniPort(Device d, Port p) {
Port ulPort = getUplinkPort(d);
if (ulPort != null) {
@@ -1638,64 +850,18 @@
return false;
}
+ /**
+ * Gets the given device details from SADIS.
+ * If the device is not found, returns null
+ *
+ * @param dev the access device
+ * @return the olt information
+ */
private SubscriberAndDeviceInformation getOltInfo(Device dev) {
String devSerialNo = dev.serialNumber();
return subsService.get(devSerialNo);
}
- private MeterId getMeterIdFromBpMapping(DeviceId deviceId, String bandwidthProfile) {
- if (bpInfoToMeter.get(bandwidthProfile) == null) {
- log.warn("Bandwidth Profile '{}' is not currently mapped to a meter",
- bandwidthProfile);
- return null;
- }
-
- Optional<MeterKey> meterKeyForDevice = bpInfoToMeter.get(bandwidthProfile)
- .stream()
- .filter(meterKey -> meterKey.deviceId().equals(deviceId))
- .findFirst();
- if (meterKeyForDevice.isPresent()) {
- log.debug("Found meter {} for bandwidth profile {}",
- meterKeyForDevice.get().meterId(), bandwidthProfile);
- return meterKeyForDevice.get().meterId();
- } else {
- log.warn("Bandwidth profile '{}' is not currently mapped to a meter",
- bandwidthProfile);
- return null;
- }
- }
-
- private void addMeterIdToBpMapping(DeviceId deviceId, MeterId meterId, String bandwidthProfile) {
-
- if (bpInfoToMeter.get(bandwidthProfile) == null) {
- bpInfoToMeter.put(bandwidthProfile,
- new ArrayList<>(Arrays.asList(MeterKey.key(deviceId, meterId))));
- } else {
- List<MeterKey> meterKeyListForBp = bpInfoToMeter.get(bandwidthProfile);
- meterKeyListForBp.add(MeterKey.key(deviceId, meterId));
- }
- }
-
- /**
- * Removes meter key from programmed meters. If the meter has no reference
- * count in the data plane and is not present in the programmed-meters store
- * it will be removed.
- *
- * @param deviceId device identifier
- * @param bandwidthProfileId name of bandwidth profile
- */
- private void removeMeterIdFromPrgMeters(DeviceId deviceId,
- String bandwidthProfileId) {
- List<MeterKey> meterKeysForBp = bpInfoToMeter.get(bandwidthProfileId);
- if (meterKeysForBp != null) {
- meterKeysForBp.stream()
- .filter(meterKey -> meterKey.deviceId().equals(deviceId))
- .findFirst().ifPresent(mk -> {
- programmedMeters.remove(mk);
- });
- }
- }
-
private class InternalDeviceListener implements DeviceListener {
private Set<DeviceId> programmedDevices = Sets.newConcurrentHashSet();
@@ -1705,126 +871,131 @@
DeviceId devId = event.subject().id();
Device dev = event.subject();
Port port = event.port();
+ DeviceEvent.Type eventType = event.type();
- if (event.type() == DeviceEvent.Type.PORT_STATS_UPDATED) {
+ if (DeviceEvent.Type.PORT_STATS_UPDATED.equals(eventType) ||
+ DeviceEvent.Type.DEVICE_SUSPENDED.equals(eventType) ||
+ DeviceEvent.Type.DEVICE_UPDATED.equals(eventType)) {
return;
}
+ log.debug("OLT got {} event for {} {}", eventType, event.subject(), event.port());
+
if (getOltInfo(dev) == null) {
// it's possible that we got an event for a previously
// programmed OLT that is no longer available in SADIS
// we let such events go through
if (!programmedDevices.contains(devId)) {
log.warn("No device info found for {}, this is either "
- + "not an OLT or not known to sadis", dev);
+ + "not an OLT or not known to sadis", dev);
return;
}
}
- log.debug("OLT got {} event for {}: {}", event.type(),
- event.subject().id(), event);
-
switch (event.type()) {
//TODO: Port handling and bookkeeping should be improved once
// olt firmware handles correct behaviour.
case PORT_ADDED:
if (isUniPort(dev, port)) {
post(new AccessDeviceEvent(AccessDeviceEvent.Type.UNI_ADDED, devId, port));
- if (port.isEnabled()) {
- processEapolFilteringObjectives(devId, port.number(), defaultBpId,
- null, VlanId.vlanId(EAPOL_DEFAULT_VLAN), true);
+
+ if (port.isEnabled() && !port.number().equals(PortNumber.LOCAL)) {
+ log.info("eapol will be sent for port added {}", port);
+ oltFlowService.processEapolFilteringObjectives(devId, port.number(), defaultBpId,
+ null,
+ VlanId.vlanId(EAPOL_DEFAULT_VLAN), true);
}
} else {
- checkAndCreateDeviceFlows(dev);
+ SubscriberAndDeviceInformation deviceInfo = getOltInfo(dev);
+ if (deviceInfo != null) {
+ oltFlowService.processNniFilteringObjectives(dev.id(), port.number(), true);
+ }
}
break;
case PORT_REMOVED:
if (isUniPort(dev, port)) {
removeSubscriber(new ConnectPoint(devId, port.number()));
- processEapolFilteringObjectives(devId, port.number(), defaultBpId,
- null, VlanId.vlanId(EAPOL_DEFAULT_VLAN), false);
+ log.info("eapol will be send for port removed", port);
+ oltFlowService.processEapolFilteringObjectives(devId, port.number(), defaultBpId,
+ null,
+ VlanId.vlanId(EAPOL_DEFAULT_VLAN), false);
post(new AccessDeviceEvent(AccessDeviceEvent.Type.UNI_REMOVED, devId, port));
}
-
break;
case PORT_UPDATED:
if (!isUniPort(dev, port)) {
break;
}
-
- SubscriberAndDeviceInformation sub = programmedSubs
+ Set<UniTagInformation> uniTagInformationSet = programmedSubs
.get(new ConnectPoint(devId, port.number()));
- VlanId vlanId = sub == null ? VlanId.vlanId(EAPOL_DEFAULT_VLAN) : sub.cTag();
-
- String bpId = getCurrentBandwidthProfile(new ConnectPoint(devId, port.number()));
-
+ if (uniTagInformationSet == null || uniTagInformationSet.isEmpty()) {
+ if (port.isEnabled() && !port.number().equals(PortNumber.LOCAL)) {
+ log.info("eapol will be processed for port updated {}", port);
+ oltFlowService.processEapolFilteringObjectives(devId, port.number(), DEFAULT_BP_ID,
+ null,
+ VlanId.vlanId(EAPOL_DEFAULT_VLAN),
+ port.isEnabled());
+ }
+ } else {
+ log.info("eapol will be processed for port updated {}", port);
+ uniTagInformationSet.forEach(uniTag ->
+ oltFlowService.processEapolFilteringObjectives(devId, port.number(),
+ uniTag.getUpstreamBandwidthProfile(), null,
+ uniTag.getPonCTag(), port.isEnabled()));
+ }
if (port.isEnabled()) {
- processEapolFilteringObjectives(devId, port.number(), bpId,
- null, vlanId, true);
-
post(new AccessDeviceEvent(AccessDeviceEvent.Type.UNI_ADDED, devId, port));
} else {
- processEapolFilteringObjectives(devId, port.number(), bpId,
- null, vlanId, false);
post(new AccessDeviceEvent(AccessDeviceEvent.Type.UNI_REMOVED, devId, port));
}
break;
case DEVICE_ADDED:
- post(new AccessDeviceEvent(
- AccessDeviceEvent.Type.DEVICE_CONNECTED, devId,
- null, null));
- programmedDevices.add(devId);
- // Send UNI_ADDED events for all existing ports
- deviceService.getPorts(devId).stream()
- .filter(p -> isUniPort(dev, p))
- .filter(Port::isEnabled)
- .forEach(p -> post(new AccessDeviceEvent(
- AccessDeviceEvent.Type.UNI_ADDED, devId, p)));
-
- checkAndCreateDeviceFlows(dev);
+ handleDeviceConnection(dev, true);
break;
case DEVICE_REMOVED:
- deviceService.getPorts(devId).stream()
- .filter(p -> isUniPort(dev, p))
- .forEach(p -> post(new AccessDeviceEvent(
- AccessDeviceEvent.Type.UNI_REMOVED, devId, p)));
- programmedDevices.remove(devId);
- removeAllSubscribers(devId);
- post(new AccessDeviceEvent(
- AccessDeviceEvent.Type.DEVICE_DISCONNECTED, devId,
- null, null));
+ handleDeviceDisconnection(dev, true);
break;
case DEVICE_AVAILABILITY_CHANGED:
if (deviceService.isAvailable(devId)) {
- post(new AccessDeviceEvent(
- AccessDeviceEvent.Type.DEVICE_CONNECTED, devId,
- null, null));
- programmedDevices.add(devId);
- checkAndCreateDeviceFlows(dev);
+ handleDeviceConnection(dev, false);
} else {
- programmedDevices.remove(devId);
- removeAllSubscribers(devId);
- post(new AccessDeviceEvent(
- AccessDeviceEvent.Type.DEVICE_DISCONNECTED, devId,
- null, null));
+ handleDeviceDisconnection(dev, false);
}
break;
- case DEVICE_UPDATED:
- case DEVICE_SUSPENDED:
- case PORT_STATS_UPDATED:
default:
return;
}
});
}
- private String getCurrentBandwidthProfile(ConnectPoint connectPoint) {
- SubscriberAndDeviceInformation sub = programmedSubs.get(connectPoint);
- if (sub != null) {
- return sub.upstreamBandwidthProfile();
+ private void sendUniEvent(Device device, AccessDeviceEvent.Type eventType) {
+ deviceService.getPorts(device.id()).stream()
+ .filter(p -> !PortNumber.LOCAL.equals(p.number()))
+ .filter(p -> isUniPort(device, p))
+ .forEach(p -> post(new AccessDeviceEvent(eventType, device.id(), p)));
+ }
+
+ private void handleDeviceDisconnection(Device device, boolean sendUniEvent) {
+ programmedDevices.remove(device.id());
+ removeAllSubscribers(device.id());
+ post(new AccessDeviceEvent(
+ AccessDeviceEvent.Type.DEVICE_DISCONNECTED, device.id(),
+ null, null, null));
+ if (sendUniEvent) {
+ sendUniEvent(device, AccessDeviceEvent.Type.UNI_REMOVED);
}
- return defaultBpId;
+ }
+
+ private void handleDeviceConnection(Device dev, boolean sendUniEvent) {
+ post(new AccessDeviceEvent(
+ AccessDeviceEvent.Type.DEVICE_CONNECTED, dev.id(),
+ null, null, null));
+ programmedDevices.add(dev.id());
+ checkAndCreateDeviceFlows(dev);
+ if (sendUniEvent) {
+ sendUniEvent(dev, AccessDeviceEvent.Type.UNI_ADDED);
+ }
}
private void removeAllSubscribers(DeviceId deviceId) {
@@ -1834,53 +1005,6 @@
connectPoints.forEach(cp -> programmedSubs.remove(cp));
}
- }
- private class InternalMeterListener implements MeterListener {
-
- @Override
- public void event(MeterEvent meterEvent) {
- if (deleteMeters && MeterEvent.Type.METER_REFERENCE_COUNT_ZERO.equals(meterEvent.type())) {
- log.debug("Zero Count Meter {} received", meterEvent.subject());
- Meter meter = meterEvent.subject();
- if (meter != null && appId.equals(meter.appId()) &&
- !programmedMeters.contains(MeterKey.key(meter.deviceId(), meter.id()))) {
- log.info("Deleting unreferenced, no longer programmed Meter {}",
- meter.id());
- deleteMeter(meter.deviceId(), meter.id());
- }
- } else if (MeterEvent.Type.METER_REMOVED.equals(meterEvent.type())) {
- log.debug("Meter removed event is received. Meter is {}",
- meterEvent.subject());
- removeMeterFromBpMap(meterEvent.subject());
- }
- }
-
- private void deleteMeter(DeviceId deviceId, MeterId meterId) {
- Meter meter = meterService.getMeter(deviceId, meterId);
- if (meter != null) {
- MeterRequest meterRequest = DefaultMeterRequest.builder()
- .withBands(meter.bands())
- .withUnit(meter.unit())
- .forDevice(deviceId)
- .fromApp(appId)
- .burst()
- .remove();
-
- meterService.withdraw(meterRequest, meterId);
- }
- }
-
- private void removeMeterFromBpMap(Meter meter) {
- bpInfoToMeter.values().forEach(meterKeys -> meterKeys.stream()
- .filter(meterKey -> (meterKey.deviceId().equals(meter.deviceId()))
- && meterKey.meterId().equals(meter.id())).findFirst().
- ifPresent(mk -> {
- meterKeys.remove(mk);
- programmedMeters.remove(mk);
- log.info("Deleted from the internal map. MeterKey {}", mk);
- log.info("Programmed meters {}", programmedMeters);
- }));
- }
}
}