import java.math.BigInteger;
import java.util.ArrayList;
+import java.util.List;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
}
return alist;
}
+ public static ArrayList<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> actionList(List<ActionBuilder> actions) {
+ ArrayList<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> alist
+ = new ArrayList<>();
+ int count = 0;
+ for (ActionBuilder action : actions) {
+ alist.add(action
+ .setOrder(Integer.valueOf(count++))
+ .build());
+ }
+ return alist;
+ }
public static Instruction applyActionIns(Action... actions) {
return new ApplyActionsCaseBuilder()
.setApplyActions(new ApplyActionsBuilder()
.build())
.build();
}
+ public static Instruction applyActionIns(List<ActionBuilder> actions) {
+ return new ApplyActionsCaseBuilder()
+ .setApplyActions(new ApplyActionsBuilder()
+ .setAction(actionList(actions))
+ .build())
+ .build();
+ }
public static Instructions instructions(Instruction... instructions) {
ArrayList<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction> ins
= new ArrayList<>();
package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
+import java.util.ArrayList;
import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.Dirty;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.RegMatch;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.AllowAction;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.Classifier;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.Action;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.SubjectFeatures;
import org.opendaylight.groupbasedpolicy.resolver.ConditionGroup;
import org.opendaylight.groupbasedpolicy.resolver.EgKey;
import org.opendaylight.groupbasedpolicy.resolver.Policy;
import org.opendaylight.groupbasedpolicy.resolver.PolicyInfo;
import org.opendaylight.groupbasedpolicy.resolver.RuleGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.action.refs.ActionRef;
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.EndpointGroup;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup.IntraGroupPolicy;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.subject.Rule;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ActionInstance;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ClassifierInstance;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.collect.ComparisonChain;
+import com.google.common.collect.Ordering;
+
import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.*;
/**
}
}
}
-
+
+ /**
+ * Private internal class for ordering Actions in Rules. The
+ * order is determined first by the value of the order parameter,
+ * with the lower order actions being applied first; for Actions
+ * with either the same order or no order, ordering is lexicographical
+ * by name.
+ *
+ * @author tbachman
+ *
+ */
+ private static class ActionRefComparator implements Comparator<ActionRef> {
+ public static final ActionRefComparator INSTANCE = new ActionRefComparator();
+
+ @Override
+ public int compare(ActionRef arg0, ActionRef arg1) {
+ return ComparisonChain.start()
+ .compare(arg0.getOrder(), arg1.getOrder(),
+ Ordering.natural().nullsLast())
+ .compare(arg0.getName().getValue(), arg1.getName().getValue(),
+ Ordering.natural().nullsLast())
+ .result();
+ }
+
+ }
+
private void syncDirection(ReadWriteTransaction t,
InstanceIdentifier<Table> tiid,
Map<String, FlowCtx> flowMap, NodeId nodeId,
IndexedTenant contractTenant,
CgPair p, Rule r, Direction d, int priority) {
+ /*
+ * Create the ordered action list. The implicit action is
+ * "allow", and is therefore always in the list
+ *
+ * TODO: revisit implicit vs. default for "allow"
+ * TODO: look into incorporating operational policy for actions
+ */
+ List<ActionBuilder> abl = new ArrayList<ActionBuilder>();
+ if (r.getActionRef() != null) {
+ /*
+ * Pre-sort by references using order, then name
+ */
+ List<ActionRef> arl = new ArrayList<ActionRef>(r.getActionRef());
+ Collections.sort(arl, ActionRefComparator.INSTANCE);
+
+ for (ActionRef ar: arl) {
+ ActionInstance ai = contractTenant.getAction(ar.getName());
+ if (ai == null) {
+ // XXX TODO fail the match and raise an exception
+ LOG.warn("Action instance {} not found",
+ ar.getName().getValue());
+ return;
+ }
+ Action act = SubjectFeatures.getAction(ai.getActionDefinitionId());
+ if (act == null) {
+ // XXX TODO fail the match and raise an exception
+ LOG.warn("Action definition {} not found",
+ ai.getActionDefinitionId().getValue());
+ return;
+ }
+
+ Map<String,Object> params = new HashMap<>();
+ if (ai.getParameterValue() != null) {
+ for (ParameterValue v : ai.getParameterValue()) {
+ if (v.getName() == null) continue;
+ if (v.getIntValue() != null) {
+ params.put(v.getName().getValue(), v.getIntValue());
+ } else if (v.getStringValue() != null) {
+ params.put(v.getName().getValue(), v.getStringValue());
+ }
+ }
+ }
+ /*
+ * Convert the GBP Action to one or more OpenFlow
+ * Actions
+ */
+ abl = act.updateAction(abl, params, ar.getOrder());
+ }
+ }
+ else {
+ Action act = SubjectFeatures.getAction(AllowAction.ID);
+ abl = act.updateAction(abl, new HashMap<String,Object>(), 0);
+ }
+
+
for (ClassifierRef cr : r.getClassifierRef()) {
if (cr.getDirection() != null &&
!cr.getDirection().equals(Direction.Bidirectional) &&
flow.setMatch(m)
.setId(flowId)
.setPriority(Integer.valueOf(priority))
- .setInstructions(instructions(applyActionIns(nxOutputRegAction(NxmNxReg7.class))));
+ .setInstructions(instructions(applyActionIns(abl)));
writeFlow(t, tiid, flow.build());
}
}
--- /dev/null
+/*
+ * 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.renderer.ofoverlay.sf;
+
+import java.util.List;
+import java.util.Map;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionDefinitionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ActionDefinition;
+
+/**
+ * Represent an action definition, and provide tools for generating
+ * flow instructions based on the action
+ * @author tbachman
+ */
+public abstract class Action {
+ /**
+ * Get the action definition for this action
+ * @return the {@link ActionDefinition} for this action
+ */
+ public abstract ActionDefinitionId getId();
+
+ /**
+ * Get the action definition for this action
+ * @return the {@link ActionDefinition} for this action
+ */
+ public abstract ActionDefinition getActionDef();
+
+ /**
+ * Construct a set of actions that will apply to the traffic. Augment
+ * the existing list of actions or add new actions. It's important
+ * that the order of the returned list be consistent however
+ * @param actions The existing actions
+ * @param params the parameters for the action instance
+ * @return the updated list of actions (may be a different length)
+ */
+ public abstract List<ActionBuilder> updateAction(List<ActionBuilder> actions,
+ Map<String, Object> params,
+ Integer i);
+}
--- /dev/null
+/*
+ * 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.renderer.ofoverlay.sf;
+
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxOutputRegAction;
+
+import java.util.List;
+import java.util.Map;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionDefinitionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Description;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ActionDefinition;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ActionDefinitionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg7;
+
+
+/**
+ * Allow action
+ */
+public class AllowAction extends Action {
+ public static final ActionDefinitionId ID =
+ new ActionDefinitionId("f942e8fd-e957-42b7-bd18-f73d11266d17");
+ protected static final String TYPE = "type";
+ protected static final ActionDefinition DEF =
+ new ActionDefinitionBuilder()
+ .setId(ID)
+ .setName(new ActionName("allow"))
+ .setDescription(new Description("Allow the specified traffic to pass"))
+ .build();
+
+ // How allow is implemented in the PolicyEnforcer table
+ private final org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action allow =
+ nxOutputRegAction(NxmNxReg7.class);
+
+ @Override
+ public ActionDefinitionId getId() {
+ return ID;
+ }
+
+ @Override
+ public ActionDefinition getActionDef() {
+ return DEF;
+ }
+
+ @Override
+ public List<ActionBuilder> updateAction(List<ActionBuilder> actions,
+ Map<String, Object> params,
+ Integer order) {
+ /*
+ * Allow action doesn't use parameters
+ * TODO: check to make sure ActionBuilder w/allow isn't already present
+ */
+ ActionBuilder ab = new ActionBuilder();
+ ab.setAction(allow)
+ .setOrder(order);
+ actions.add(ab);
+ return actions;
+ }
+
+}
}
));
- public static final ActionDefinition ALLOW =
- new ActionDefinitionBuilder()
- .setId(new ActionDefinitionId("f942e8fd-e957-42b7-bd18-f73d11266d17"))
- .setName(new ActionName("allow"))
- .setDescription(new Description("Allow the specified traffic to pass"))
- .build();
+ private static final Map<ActionDefinitionId, Action> actions =
+ ImmutableMap.<ActionDefinitionId, Action>
+ of(AllowAction.ID, new AllowAction());
+
+ public static final List<ActionDefinition> actionDefs =
+ ImmutableList.copyOf(Collections2.transform(actions.values(),
+ new Function<Action, ActionDefinition>() {
+ @Override
+ public ActionDefinition apply(Action input) {
+ return input.getActionDef();
+ }
+ }
+ ));
+
public static final SubjectFeatureDefinitions OF_OVERLAY_FEATURES =
new SubjectFeatureDefinitionsBuilder()
- .setActionDefinition(ImmutableList.of(ALLOW))
+ .setActionDefinition(actionDefs)
.setClassifierDefinition(classifierDefs)
.build();
public static Classifier getClassifier(ClassifierDefinitionId id) {
return classifiers.get(id);
}
+
+ /**
+ * Get the {@link Action} associated with the given
+ * {@link ActionDefinitionId}
+ * @param id the {@link ActionDefinitionId} to look up
+ * @return the {@link Action} if one exists, or <code>null</code>
+ * otherwise
+ */
+ public static Action getAction(ActionDefinitionId id) {
+ return actions.get(id);
+ }
}
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.MockPolicyManager;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.MockSwitchManager;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OfTable.OfTableCtx;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.AllowAction;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.L4Classifier;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.SubjectFeatures;
import org.opendaylight.groupbasedpolicy.resolver.MockPolicyResolver;
.build()))
.setActionInstance(ImmutableList.of(new ActionInstanceBuilder()
.setName(new ActionName("allow"))
- .setActionDefinitionId(SubjectFeatures.ALLOW.getId())
+ .setActionDefinitionId(new AllowAction().getId())
.build()))
.build())
.setContract(ImmutableList.of(new ContractBuilder()