blob: e37d30c7a3247f5de7c27bc9b1b23b64bd235693 [file] [log] [blame]
/*
* Copyright 2015-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Originally created by Pengfei Lu, Network and Cloud Computing Laboratory, Dalian University of Technology, China
* Advisers: Keqiu Li, Heng Qi and Haisheng Yu
* This work is supported by the State Key Program of National Natural Science of China(Grant No. 61432002)
* and Prospective Research Project on Future Networks in Jiangsu Future Networks Innovation Institute.
*/
package org.onosproject.acl.impl;
import com.google.common.collect.Collections2;
import org.onosproject.acl.AclRule;
import org.onosproject.acl.AclStore;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.util.KryoNamespace;
import org.onosproject.acl.RuleId;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.DeviceId;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.store.AbstractStore;
import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.ConsistentMap;
import org.onosproject.store.service.Serializer;
import org.onosproject.store.service.StorageService;
import org.onosproject.store.service.Versioned;
import org.slf4j.Logger;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Implementation of the ACL store service.
*/
@Component(immediate = true)
@Service
public class DistributedAclStore extends AbstractStore implements AclStore {
private final Logger log = getLogger(getClass());
private final int defaultFlowMaxPriority = 30000;
private ConsistentMap<RuleId, AclRule> ruleSet;
private ConsistentMap<DeviceId, Integer> deviceToPriority;
private ConsistentMap<RuleId, Set<DeviceId>> ruleToDevice;
private ConsistentMap<RuleId, Set<FlowRule>> ruleToFlow;
private ConsistentMap<RuleId, List<RuleId>> denyRuleToAllowRule;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected StorageService storageService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
@Activate
public void activate() {
ApplicationId appId = coreService.getAppId("org.onosproject.acl");
KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
.register(KryoNamespaces.API)
.register(AclRule.class)
.register(AclRule.Action.class)
.register(RuleId.class);
ruleSet = storageService.<RuleId, AclRule>consistentMapBuilder()
.withSerializer(Serializer.using(serializer.build()))
.withName("acl-rule-set")
.withApplicationId(appId)
.withPurgeOnUninstall()
.build();
deviceToPriority = storageService.<DeviceId, Integer>consistentMapBuilder()
.withSerializer(Serializer.using(serializer.build()))
.withName("device-to-priority")
.withApplicationId(appId)
.withPurgeOnUninstall()
.build();
ruleToFlow = storageService.<RuleId, Set<FlowRule>>consistentMapBuilder()
.withSerializer(Serializer.using(serializer.build()))
.withName("rule-to-flow")
.withApplicationId(appId)
.withPurgeOnUninstall()
.build();
denyRuleToAllowRule = storageService.<RuleId, List<RuleId>>consistentMapBuilder()
.withSerializer(Serializer.using(serializer.build()))
.withName("deny-to-allow")
.withApplicationId(appId)
.withPurgeOnUninstall()
.build();
ruleToDevice = storageService.<RuleId, Set<DeviceId>>consistentMapBuilder()
.withSerializer(Serializer.using(serializer.build()))
.withName("rule-to-device")
.withApplicationId(appId)
.withPurgeOnUninstall()
.build();
log.info("Started");
}
@Deactivate
public void deactive() {
log.info("Stopped");
}
@Override
public List<AclRule> getAclRules() {
List<AclRule> aclRules = new ArrayList<>();
aclRules.addAll(Collections2.transform(ruleSet.values(), Versioned::value));
return aclRules;
}
@Override
public void addAclRule(AclRule rule) {
ruleSet.putIfAbsent(rule.id(), rule);
}
@Override
public AclRule getAclRule(RuleId ruleId) {
Versioned<AclRule> rule = ruleSet.get(ruleId);
if (rule != null) {
return rule.value();
} else {
return null;
}
}
@Override
public void removeAclRule(RuleId ruleId) {
ruleSet.remove(ruleId);
}
@Override
public void clearAcl() {
ruleSet.clear();
deviceToPriority.clear();
ruleToFlow.clear();
denyRuleToAllowRule.clear();
ruleToDevice.clear();
}
@Override
public int getPriorityByDevice(DeviceId deviceId) {
return deviceToPriority.compute(deviceId,
(id, priority) -> (priority == null) ? defaultFlowMaxPriority : (priority - 1))
.value();
}
@Override
public Set<FlowRule> getFlowByRule(RuleId ruleId) {
Versioned<Set<FlowRule>> flowRuleSet = ruleToFlow.get(ruleId);
if (flowRuleSet != null) {
return flowRuleSet.value();
} else {
return null;
}
}
@Override
public void addRuleToFlowMapping(RuleId ruleId, FlowRule flowRule) {
ruleToFlow.computeIf(ruleId,
flowRuleSet -> (flowRuleSet == null || !flowRuleSet.contains(flowRule)),
(id, flowRuleSet) -> {
Set<FlowRule> newSet = new HashSet<>();
if (flowRuleSet != null) {
newSet.addAll(flowRuleSet);
}
newSet.add(flowRule);
return newSet;
});
}
@Override
public void removeRuleToFlowMapping(RuleId ruleId) {
ruleToFlow.remove(ruleId);
}
@Override
public List<RuleId> getAllowingRuleByDenyingRule(RuleId denyingRuleId) {
Versioned<List<RuleId>> allowRuleIdSet = denyRuleToAllowRule.get(denyingRuleId);
if (allowRuleIdSet != null) {
return allowRuleIdSet.value();
} else {
return null;
}
}
@Override
public void addDenyToAllowMapping(RuleId denyingRuleId, RuleId allowingRuleId) {
denyRuleToAllowRule.computeIf(denyingRuleId,
ruleIdList -> (ruleIdList == null || !ruleIdList.contains(allowingRuleId)),
(id, ruleIdList) -> {
ArrayList<RuleId> newList = new ArrayList<>();
if (ruleIdList != null) {
newList.addAll(ruleIdList);
}
newList.add(allowingRuleId);
return newList;
});
}
@Override
public void removeDenyToAllowMapping(RuleId denyingRuleId) {
denyRuleToAllowRule.remove(denyingRuleId);
}
@Override
public boolean checkIfRuleWorksInDevice(RuleId ruleId, DeviceId deviceId) {
return ruleToDevice.containsKey(ruleId) && ruleToDevice.get(ruleId).value().contains(deviceId);
}
@Override
public void addRuleToDeviceMapping(RuleId ruleId, DeviceId deviceId) {
ruleToDevice.computeIf(ruleId,
deviceIdSet -> (deviceIdSet == null || !deviceIdSet.contains(deviceId)),
(id, deviceIdSet) -> {
Set<DeviceId> newSet = new HashSet<>();
if (deviceIdSet != null) {
newSet.addAll(deviceIdSet);
}
newSet.add(deviceId);
return newSet;
});
}
@Override
public void removeRuleToDeviceMapping(RuleId ruleId) {
ruleToDevice.remove(ruleId);
}
}