/* * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.rule; import java.util.List; import javax.annotation.concurrent.Immutable; import org.opendaylight.groupbasedpolicy.api.sf.EtherTypeClassifierDefinition; import org.opendaylight.groupbasedpolicy.api.sf.IpProtoClassifierDefinition; import org.opendaylight.groupbasedpolicy.api.sf.L4ClassifierDefinition; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.change.action.of.security.group.rules.input.action.ActionChoice; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.change.action.of.security.group.rules.input.action.action.choice.SfcActionCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRef; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.subject.Rule; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.subject.RuleBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ClassifierInstance; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.security.rules.SecurityRule; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; @Immutable public class SingleClassifierRule { private final ClassifierInstance classifierInstance; private final ClassifierRef classifierRef; private final Rule rule; public SingleClassifierRule(SecurityRule secRule, int ruleBaseOrder, ActionChoice action) { classifierInstance = SecRuleEntityDecoder.getClassifierInstance(secRule); classifierRef = SecRuleEntityDecoder.getClassifierRef(secRule); rule = createRule( updateOrderBasedOn(classifierInstance, action, ruleBaseOrder), secRule, action); } public ClassifierInstance getClassifierInstance() { return classifierInstance; } public ClassifierRef getClassifierRef() { return classifierRef; } public Rule getRule() { return rule; } private Rule createRule(int order, SecurityRule secRule, ActionChoice action) { return new RuleBuilder().setName(SecRuleNameDecoder.getRuleName(secRule)) .setOrder(order) .setActionRef(ImmutableList.of(SecRuleEntityDecoder.createActionRefFromActionChoice(action))) .setClassifierRef(ImmutableList.<ClassifierRef>of(classifierRef)) .build(); } /** * Increases initial order of potential {@link Rule} containing single * {@link ClassifierInstance} based on parameter values of the instance. * <br> * The following section describes how L4 port specification is prioritized * from most specific to least specific:<br> * 1) src port AND dst port<br> * 2) (src port range AND dst port) OR (src port AND dst port range)<br> * 3) src port range AND dst port range<br> * 4) src port OR dst port<br> * 5) src port range OR dst port range<br> * * @param ci instance object of {@link ClassifierInstance} * @param baseOrder initial order value calculated for the {@link Rule} * @return value of incremented order based on parameter values. * * @see ParameterValue */ @VisibleForTesting static int updateOrderBasedOn(ClassifierInstance ci, ActionChoice action, Integer baseOrder) { int delta = 0; if (ci.getClassifierDefinitionId().equals(EtherTypeClassifierDefinition.ID)) { delta = 350; } else if (ci.getClassifierDefinitionId().equals(IpProtoClassifierDefinition.ID)) { delta = 300; } else if (ci.getClassifierDefinitionId().equals(L4ClassifierDefinition.ID)) { delta = 200; List<ParameterValue> parameterValue = ci.getParameterValue(); for (ParameterValue pv : parameterValue) { // SRC/DST_PORT_PARAM is considered to be more // specific than SRC/DST_PORT_RANGE_PARAM. if (isSrcOrDstPortParam(pv)) { delta -= 30; } else if (isRangePortParam(pv)) { delta -= pv.getRangeValue().getMin().equals(pv.getRangeValue().getMax()) ? 30 : 20; } } } if (action instanceof SfcActionCase) { delta -= 5; } // more specific CIs should have lower order calculated. return baseOrder + delta; } private static boolean isRangePortParam(ParameterValue pv) { String pvName = pv.getName().getValue(); return pv.getRangeValue() != null && (pvName.equals(L4ClassifierDefinition.SRC_PORT_RANGE_PARAM) || pvName.equals(L4ClassifierDefinition.DST_PORT_RANGE_PARAM)); } private static boolean isSrcOrDstPortParam(ParameterValue pv) { String pvName = pv.getName().getValue(); return pv.getIntValue() != null && (pvName.equals(L4ClassifierDefinition.SRC_PORT_PARAM) || pvName.equals(L4ClassifierDefinition.DST_PORT_PARAM)); } }