| /* |
| * 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.onlab.util.KryoNamespace; |
| import org.onosproject.acl.AclRule; |
| import org.onosproject.acl.AclStore; |
| 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.osgi.service.component.annotations.Activate; |
| import org.osgi.service.component.annotations.Component; |
| import org.osgi.service.component.annotations.Deactivate; |
| import org.osgi.service.component.annotations.Reference; |
| import org.osgi.service.component.annotations.ReferenceCardinality; |
| 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 = AclStore.class) |
| 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) |
| protected StorageService storageService; |
| @Reference(cardinality = ReferenceCardinality.MANDATORY) |
| 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); |
| } |
| |
| } |