package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.rule;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+
import javax.annotation.concurrent.Immutable;
-import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
-import org.opendaylight.neutron.spi.NeutronSecurityRule;
+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 com.google.common.collect.ImmutableList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.security.rules.SecurityRule;
@Immutable
public class SingleClassifierRule {
private final ClassifierRef classifierRef;
private final Rule rule;
- public SingleClassifierRule(NeutronSecurityRule secRule, int ruleOrder) {
+ public SingleClassifierRule(SecurityRule secRule, int ruleBaseOrder, ActionChoice action) {
classifierInstance = SecRuleEntityDecoder.getClassifierInstance(secRule);
classifierRef = SecRuleEntityDecoder.getClassifierRef(secRule);
- rule = createRule(ruleOrder, secRule);
- }
-
- private Rule createRule(int order, NeutronSecurityRule secRule) {
- return new RuleBuilder().setName(SecRuleNameDecoder.getRuleName(secRule))
- .setOrder(order)
- .setActionRef(MappingUtils.ACTION_REF_ALLOW)
- .setClassifierRef(ImmutableList.of(classifierRef))
- .build();
+ rule = createRule(
+ updateOrderBasedOn(classifierInstance, action, ruleBaseOrder),
+ secRule,
+ action);
}
public ClassifierInstance getClassifierInstance() {
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));
+ }
+
}