import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ScheduledExecutorService;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
import org.opendaylight.groupbasedpolicy.endpoint.AbstractEndpointRegistry;
import org.opendaylight.groupbasedpolicy.resolver.EgKey;
-import org.opendaylight.groupbasedpolicy.resolver.EndpointProvider;
import org.opendaylight.groupbasedpolicy.util.SetUtils;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.Endpoints;
import org.slf4j.LoggerFactory;
import com.google.common.base.Function;
+import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
+import com.google.common.collect.Sets;
/**
* Keep track of endpoints on the system. Maintain an index of endpoints
*/
public class EndpointManager
extends AbstractEndpointRegistry
- implements AutoCloseable, DataChangeListener, EndpointProvider
+ implements AutoCloseable, DataChangeListener
{
private static final Logger LOG =
LoggerFactory.getLogger(EndpointManager.class);
private final ConcurrentHashMap<EpKey, Endpoint> endpoints =
new ConcurrentHashMap<>();
- private final ConcurrentHashMap<NodeId, Set<EpKey>> endpointsByNode =
+ private final ConcurrentHashMap<NodeId,
+ ConcurrentMap<EgKey, Set<EpKey>>> endpointsByNode =
new ConcurrentHashMap<>();
private final ConcurrentHashMap<EgKey, Set<EpKey>> endpointsByGroup =
new ConcurrentHashMap<>();
-
+
private List<EndpointListener> listeners = new CopyOnWriteArrayList<>();
public EndpointManager(DataBroker dataProvider,
* @param nodeId the nodeId of the switch to get endpoints for
* @return a collection of {@link Endpoint} objects.
*/
- public Collection<Endpoint> getEndpointsForNode(NodeId nodeId) {
- Collection<EpKey> ebn = endpointsByNode.get(nodeId);
+ public Set<EgKey> getGroupsForNode(NodeId nodeId) {
+ Map<EgKey, Set<EpKey>> nodeEps = endpointsByNode.get(nodeId);
+ if (nodeEps == null) return Collections.emptySet();
+ return Collections.unmodifiableSet(nodeEps.keySet());
+ }
+
+ /**
+ * Get the set of nodes
+ * @param nodeId the nodeId of the switch to get endpoints for
+ * @return a collection of {@link Endpoint} objects.
+ */
+ public Set<NodeId> getNodesForGroup(final EgKey egKey) {
+ return Collections.unmodifiableSet(Sets.filter(endpointsByNode.keySet(),
+ new Predicate<NodeId>() {
+ @Override
+ public boolean apply(NodeId input) {
+ Map<EgKey, Set<EpKey>> nodeEps =
+ endpointsByNode.get(input);
+ return (nodeEps != null &&
+ nodeEps.containsKey(egKey));
+ }
+
+ }));
+ }
+
+ /**
+ * Get the endpoints in a particular group on a particular node
+ * @param nodeId the node ID to look up
+ * @param eg the group to look up
+ * @return the endpoints
+ */
+ public Collection<Endpoint> getEPsForNode(NodeId nodeId, EgKey eg) {
+ Map<EgKey, Set<EpKey>> nodeEps = endpointsByNode.get(nodeId);
+ if (nodeEps == null) return Collections.emptyList();
+ Collection<EpKey> ebn = nodeEps.get(eg);
if (ebn == null) return Collections.emptyList();
- return Collections2.transform(ebn, indexTransform);
+ return Collections.unmodifiableCollection(Collections2
+ .transform(ebn,
+ indexTransform));
}
/**
public void setLearningMode(LearningMode learningMode) {
// No-op for now
}
-
- // ****************
- // EndpointProvider
- // ****************
-
- @Override
+
+ /**
+ * Get a collection of endpoints in a particular endpoint group
+ * @param nodeId the nodeId of the switch to get endpoints for
+ * @return a collection of {@link Endpoint} objects.
+ */
public Collection<Endpoint> getEndpointsForGroup(EgKey eg) {
Collection<EpKey> ebg = endpointsByGroup.get(eg);
if (ebg == null) return Collections.emptyList();
return Collections2.transform(ebg, indexTransform);
}
- @Override
+ /**
+ * Get the effective list of conditions that apply to a particular
+ * endpoint. This could include additional conditions over the condition
+ * labels directly represented in the endpoint object
+ * @param endpoint the {@link Endpoint} to resolve
+ * @return the list of {@link ConditionName}
+ */
public List<ConditionName> getCondsForEndpoint(Endpoint endpoint) {
// XXX TODO consider group conditions as well. Also need to notify
// endpoint updated if the endpoint group conditions change
return endpoint.getCondition();
else return Collections.emptyList();
}
-
+
// ************************
// AbstractEndpointRegistry
// ************************
return new EgKey(endpoint.getTenant(), endpoint.getEndpointGroup());
}
- private Set<EpKey> getEpNSet(NodeId location) {
- return SetUtils.getNestedSet(location, endpointsByNode);
+ private Set<EpKey> getEpNGSet(NodeId location, EgKey eg) {
+ ConcurrentMap<EgKey, Set<EpKey>> map = endpointsByNode.get(location);
+ if (map == null) {
+ map = new ConcurrentHashMap<>();
+ ConcurrentMap<EgKey, Set<EpKey>> old =
+ endpointsByNode.putIfAbsent(location, map);
+ if (old != null)
+ map = old;
+ }
+ return SetUtils.getNestedSet(eg, map);
}
+
+ private static final ConcurrentMap<EgKey, Set<EpKey>> EMPTY_MAP =
+ new ConcurrentHashMap<>();
private Set<EpKey> getEpGSet(EgKey eg) {
return SetUtils.getNestedSet(eg, endpointsByGroup);
if (newEp != null)
endpoints.put(epKey, newEp);
- if (oldLoc != null &&
- (newLoc == null || !oldLoc.equals(newLoc))) {
- Set<EpKey> eps = getEpNSet(oldLoc);
+ if (oldLoc != null && oldKey != null &&
+ (newLoc == null || !oldLoc.equals(newLoc) ||
+ newKey == null || !oldKey.equals(newKey))) {
+ ConcurrentMap<EgKey, Set<EpKey>> map =
+ endpointsByNode.get(oldLoc);
+ Set<EpKey> eps = map.get(oldKey);
eps.remove(epKey);
+ map.remove(oldKey, Collections.emptySet());
+ endpointsByNode.remove(oldLoc, EMPTY_MAP);
notifyOldLoc = true;
}
if (oldKey != null &&
notifyOldEg = true;
}
- if (newLoc != null) {
- Set<EpKey> eps = getEpNSet(newLoc);
+ if (newLoc != null && newKey != null) {
+ Set<EpKey> eps = getEpNGSet(newLoc, newKey);
eps.add(epKey);
LOG.debug("Endpoint {} added to node {}", epKey, newLoc);
notifyNewLoc = true;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.DestinationMapper;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowTable;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowTable.FlowTableCtx;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.GroupTable;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OfTable;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OfTable.OfTableCtx;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.PolicyEnforcer;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.PortSecurity;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.SourceMapper;
import org.opendaylight.groupbasedpolicy.util.SingletonTask;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
-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.TableBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.UniqueId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayConfig.LearningMode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
/**
* The flow tables that make up the processing pipeline
*/
- private final List<? extends FlowTable> flowPipeline;
+ private final List<? extends OfTable> flowPipeline;
/**
* The delay before triggering the flow update task in response to an
// should ultimately involve some sort of distributed agreement
// or a leader to allocate them. For now we'll just use a counter and
// this local map. Also theoretically need to garbage collect periodically
- private final ConcurrentMap<TenantId, ConcurrentMap<String, Integer>> ordinals =
+ private final ConcurrentMap<String, Integer> ordinals =
new ConcurrentHashMap<>();
// XXX - need to garbage collect
private final ConcurrentMap<ConditionGroup, Integer> cgOrdinals =
t.submit();
}
- FlowTableCtx ctx = new FlowTableCtx(dataBroker, rpcRegistry,
- this, policyResolver, switchManager,
- endpointManager, executor);
+ OfTableCtx ctx = new OfTableCtx(dataBroker, rpcRegistry,
+ this, policyResolver, switchManager,
+ endpointManager, executor);
flowPipeline = ImmutableList.of(new PortSecurity(ctx),
new SourceMapper(ctx),
new DestinationMapper(ctx),
- new PolicyEnforcer(ctx));
+ new PolicyEnforcer(ctx),
+ new GroupTable(ctx));
policyScope = policyResolver.registerListener(this);
if (switchManager != null)
@Override
public void switchReady(final NodeId nodeId) {
- WriteTransaction t = dataBroker.newWriteOnlyTransaction();
-
- NodeBuilder nb = new NodeBuilder()
- .setId(nodeId)
- .addAugmentation(FlowCapableNode.class,
- new FlowCapableNodeBuilder()
- .setTable(Lists.transform(flowPipeline,
- new Function<FlowTable, Table>() {
- @Override
- public Table apply(FlowTable input) {
- return new TableBuilder()
- .setId(Short.valueOf(input.getTableId()))
- .build();
- }
- })) .build());
- t.put(LogicalDatastoreType.CONFIGURATION,
- FlowUtils.createNodePath(nodeId),
- nb.build());
- ListenableFuture<Void> result = t.submit();
- Futures.addCallback(result,
- new FutureCallback<Void>() {
- @Override
- public void onSuccess(Void result) {
- dirty.get().addNode(nodeId);
- scheduleUpdate();
- }
-
- @Override
- public void onFailure(Throwable t) {
- LOG.error("Could not add switch {}", nodeId, t);
- }
- });
+// WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+//
+// NodeBuilder nb = new NodeBuilder()
+// .setId(nodeId)
+// .addAugmentation(FlowCapableNode.class,
+// new FlowCapableNodeBuilder()
+// .build());
+// t.merge(LogicalDatastoreType.CONFIGURATION,
+// FlowUtils.createNodePath(nodeId),
+// nb.build(), true);
+// ListenableFuture<Void> result = t.submit();
+// Futures.addCallback(result,
+// new FutureCallback<Void>() {
+// @Override
+// public void onSuccess(Void result) {
+// dirty.get().addNode(nodeId);
+// scheduleUpdate();
+// }
+//
+// @Override
+// public void onFailure(Throwable t) {
+// LOG.error("Could not add switch {}", nodeId, t);
+// }
+// });
}
}
return ord.intValue();
}
-
+
/**
* Get a 32-bit context ordinal suitable for use in the OF data plane
- * for the given policy item. Note that this function may block
+ * for the given policy item.
* @param tenantId the tenant ID of the element
* @param id the unique ID for the element
* @return the 32-bit ordinal value
public int getContextOrdinal(final TenantId tenantId,
final UniqueId id) throws Exception {
if (tenantId == null || id == null) return 0;
- ConcurrentMap<String, Integer> m = ordinals.get(tenantId);
- if (m == null) {
- m = new ConcurrentHashMap<>();
- ConcurrentMap<String, Integer> old =
- ordinals.putIfAbsent(tenantId, m);
- if (old != null) m = old;
- }
- Integer ord = m.get(id.getValue());
+ return getContextOrdinal(tenantId.getValue() + "|" + id.getValue());
+ }
+
+ /**
+ * Get a 32-bit context ordinal suitable for use in the OF data plane
+ * for the given policy item.
+ * @param id the unique ID for the element
+ * @return the 32-bit ordinal value
+ */
+ public int getContextOrdinal(final String id) throws Exception {
+
+ Integer ord = ordinals.get(id);
if (ord == null) {
ord = policyOrdinal.getAndIncrement();
- Integer old = m.putIfAbsent(id.getValue(), ord);
+ Integer old = ordinals.putIfAbsent(id, ord);
if (old != null) ord = old;
}
-
return ord.intValue();
-// while (true) {
-// final ReadWriteTransaction t = dataBroker.newReadWriteTransaction();
-// InstanceIdentifier<DataPlaneOrdinal> iid =
-// InstanceIdentifier.builder(OfOverlayOperational.class)
-// .child(DataPlaneOrdinal.class,
-// new DataPlaneOrdinalKey(id, tenantId))
-// .build();
-// ListenableFuture<Optional<DataObject>> r =
-// t.read(LogicalDatastoreType.OPERATIONAL, iid);
-// Optional<DataObject> res = r.get();
-// if (res.isPresent()) {
-// DataPlaneOrdinal o = (DataPlaneOrdinal)res.get();
-// return o.getOrdinal().intValue();
-// }
-// final int ordinal = policyOrdinal.getAndIncrement();
-// OfOverlayOperational oo = new OfOverlayOperationalBuilder()
-// .setDataPlaneOrdinal(ImmutableList.of(new DataPlaneOrdinalBuilder()
-// .setId(id)
-// .setTenant(tenantId)
-// .setOrdinal(Long.valueOf(ordinal))
-// .build()))
-// .build();
-// t.merge(LogicalDatastoreType.OPERATIONAL,
-// InstanceIdentifier.builder(OfOverlayOperational.class)
-// .build(),
-// oo);
-// ListenableFuture<RpcResult<TransactionStatus>> commitr = t.commit();
-// try {
-// commitr.get();
-// return ordinal;
-// } catch (ExecutionException e) {
-// if (e.getCause() instanceof OptimisticLockFailedException)
-// continue;
-// throw e;
-// }
-// }
}
// **************
if (!switchManager.isSwitchReady(nodeId)) return null;
PolicyInfo info = policyResolver.getCurrentPolicy();
if (info == null) return null;
- for (FlowTable table : flowPipeline) {
+ for (OfTable table : flowPipeline) {
try {
table.update(nodeId, info, dirty);
} catch (Exception e) {
public static final MacAddress ROUTER_MAC =
new MacAddress("88:f0:31:b5:12:b5");
- public DestinationMapper(FlowTableCtx ctx) {
+ public DestinationMapper(OfTable.OfTableCtx ctx) {
super(ctx);
}
dropFlow(t, tiid, flowMap, Integer.valueOf(1), null);
HashSet<EgKey> visitedEgs = new HashSet<>();
- for (Endpoint e : ctx.epManager.getEndpointsForNode(nodeId)) {
- if (e.getTenant() == null || e.getEndpointGroup() == null)
- continue;
- EgKey key = new EgKey(e.getTenant(), e.getEndpointGroup());
-
- Set<EgKey> peers = Sets.union(Collections.singleton(key),
- policyInfo.getPeers(key));
+ for (EgKey epg : ctx.epManager.getGroupsForNode(nodeId)) {
+ Set<EgKey> peers = Sets.union(Collections.singleton(epg),
+ policyInfo.getPeers(epg));
for (EgKey peer : peers) {
- syncEPG(t, tiid, flowMap, nodeId, policyInfo, peer, visitedEgs);
+ syncEPG(t, tiid, flowMap, nodeId,
+ policyInfo, peer, visitedEgs);
}
}
}
import java.util.HashMap;
import java.util.Map;
-import java.util.concurrent.ScheduledExecutorService;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.EndpointManager;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.Dirty;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.SwitchManager;
import org.opendaylight.groupbasedpolicy.resolver.PolicyInfo;
-import org.opendaylight.groupbasedpolicy.resolver.PolicyResolver;
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.Flow;
import org.slf4j.LoggerFactory;
import com.google.common.base.Optional;
-import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
/**
- * Manage the state of a flow table by reacting to any events and updating
- * the table state. This is an abstract class that must be extended for
- * each specific flow table being managed.
+ * Base class for managing flow tables
* @author readams
*/
-public abstract class FlowTable {
+public abstract class FlowTable extends OfTable {
protected static final Logger LOG =
LoggerFactory.getLogger(FlowTable.class);
- /**
- * The context needed for flow tables
- */
- public static class FlowTableCtx {
- protected final DataBroker dataBroker;
- protected final RpcProviderRegistry rpcRegistry;
-
- protected final PolicyManager policyManager;
- protected final SwitchManager switchManager;
- protected final EndpointManager epManager;
-
- protected final PolicyResolver policyResolver;
-
- protected final ScheduledExecutorService executor;
-
- public FlowTableCtx(DataBroker dataBroker,
- RpcProviderRegistry rpcRegistry,
- PolicyManager policyManager,
- PolicyResolver policyResolver,
- SwitchManager switchManager,
- EndpointManager endpointManager,
- ScheduledExecutorService executor) {
- super();
- this.dataBroker = dataBroker;
- this.rpcRegistry = rpcRegistry;
- this.policyManager = policyManager;
- this.switchManager = switchManager;
- this.epManager = endpointManager;
- this.policyResolver = policyResolver;
- this.executor = executor;
- }
-
- }
-
- protected final FlowTableCtx ctx;
-
- public FlowTable(FlowTableCtx ctx) {
- super();
- this.ctx = ctx;
+ public FlowTable(OfTableCtx ctx) {
+ super(ctx);
}
- // *********
- // FlowTable
- // *********
+ // *******
+ // OfTable
+ // *******
- /**
- * Update the relevant flow table for the node
- * @param nodeId the node to update
- * @param dirty the dirty set
- * @throws Exception
- */
+ @Override
public void update(NodeId nodeId, PolicyInfo policyInfo,
Dirty dirty) throws Exception {
ReadWriteTransaction t = ctx.dataBroker.newReadWriteTransaction();
Futures.addCallback(result, updateCallback);
}
+ // *********
+ // FlowTable
+ // *********
+
/**
* Sync flow state using the flow map
* @throws Exception
.setIdleTimeout(0);
}
- /**
- * Generic callback for handling result of flow manipulation
- * @author readams
- *
- * @param <T> the expected output type
- */
- protected static class FlowCallback<T> implements FutureCallback<T> {
- @Override
- public void onSuccess(T result) {
- }
-
- @Override
- public void onFailure(Throwable t) {
- LOG.error("Failed to add flow entry", t);
- }
- }
- protected static final FlowCallback<Void> updateCallback =
- new FlowCallback<>();
-
/**
* "Visit" a flow ID by checking if it already exists and if so marking
* the {@link FlowCtx} visited bit.
LOG.trace("{} {}", flow.getId(), flow);
t.put(LogicalDatastoreType.CONFIGURATION,
FlowUtils.createFlowPath(tiid, flow.getId()),
- flow);
+ flow, true);
}
/**
import java.util.ArrayList;
+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;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DecNwTtlCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.go.to.table._case.GoToTableBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.actions._case.WriteActionsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.BucketId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.Buckets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.BucketKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
/**
* Creates a table path from a node ID and table ID
*
- * @param nodePath
- * @param tableKey
- * @return
+ * @param nodeId the ID of the node
+ * @param tableId the ID of the table
+ * @return the {@link InstanceIdentifier<Table>}
*/
public static final InstanceIdentifier<Table>
createTablePath(final NodeId nodeId,
.child(Table.class, new TableKey(tableId))
.build();
}
-
+
+ /**
+ * Creates a group path from a node ID and group ID
+ *
+ * @param nodeId the Id of the node
+ * @param groupId the ID of the group table
+ * @return the {@link InstanceIdentifier<Group>}
+ */
+ public static final InstanceIdentifier<Group>
+ createGroupPath(final NodeId nodeId,
+ final GroupId groupId) {
+ return createNodePath(nodeId).builder()
+ .augmentation(FlowCapableNode.class)
+ .child(Group.class, new GroupKey(groupId))
+ .build();
+ }
+ /**
+ * Creates a group path from a node ID and group ID
+ *
+ * @param nodeId the Id of the node
+ * @param groupId the ID of the group table
+ * @param bucketId the ID of the bucket in the group table
+ * @return the {@link InstanceIdentifier<Bucket>}
+ */
+ public static final InstanceIdentifier<Bucket>
+ createBucketPath(final NodeId nodeId,
+ final GroupId groupId,
+ final BucketId bucketId) {
+ return createNodePath(nodeId).builder()
+ .augmentation(FlowCapableNode.class)
+ .child(Group.class, new GroupKey(groupId))
+ .child(Buckets.class)
+ .child(Bucket.class, new BucketKey(bucketId))
+ .build();
+ }
+
/**
* Creates a path for particular flow, by appending flow-specific information
* to table path.
public static Instruction outputActionIns(NodeConnectorId id) {
return writeActionIns(outputAction(id));
}
-
- public static Instruction writeActionIns(Action... actions) {
+
+ public static ArrayList<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> writeActionList(Action... actions) {
ArrayList<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> alist
= new ArrayList<>();
int count = 0;
for (Action action : actions) {
alist.add(new ActionBuilder()
- .setOrder(Integer.valueOf(count++))
- .setAction(action)
- .build());
+ .setOrder(Integer.valueOf(count++))
+ .setAction(action)
+ .build());
}
+ return alist;
+ }
+
+ public static Instruction writeActionIns(Action... actions) {
return new WriteActionsCaseBuilder()
.setWriteActions(new WriteActionsBuilder()
- .setAction(alist)
+ .setAction(writeActionList(actions))
.build())
.build();
}
public static Action outputAction(NodeConnectorId id) {
return new OutputActionCaseBuilder()
.setOutputAction(new OutputActionBuilder()
- .setOutputNodeConnector(id)
+ .setOutputNodeConnector(new Uri(id.getValue()))
.build())
.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.flow;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.Dirty;
+import org.opendaylight.groupbasedpolicy.resolver.EgKey;
+import org.opendaylight.groupbasedpolicy.resolver.IndexedTenant;
+import org.opendaylight.groupbasedpolicy.resolver.PolicyInfo;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.BucketId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.Buckets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.BucketsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.BucketBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.EndpointLocation.LocationType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
+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.L2FloodDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
+
+/**
+ * Manage the group tables for handling broadcast/multicast
+ * @author readams
+ */
+public class GroupTable extends OfTable {
+ private static final Logger LOG =
+ LoggerFactory.getLogger(GroupTable.class);
+
+ public GroupTable(OfTableCtx ctx) {
+ super(ctx);
+ // TODO Auto-generated constructor stub
+ }
+
+ @Override
+ public void update(NodeId nodeId, PolicyInfo policyInfo, Dirty dirty)
+ throws Exception {
+ // there appears to be no way of getting only the existing group
+ // tables unfortunately, so we have to get the whole goddamned node.
+ // Since this is happening concurrently with other things that are
+ // working in subtrees of nodes, we have to do two transactions
+ ReadOnlyTransaction t = ctx.dataBroker.newReadOnlyTransaction();
+ InstanceIdentifier<Node> niid =
+ FlowUtils.createNodePath(nodeId);
+ Optional<Node> r =
+ t.read(LogicalDatastoreType.CONFIGURATION, niid).get();
+ if (!r.isPresent()) return;
+ FlowCapableNode fcn = r.get().getAugmentation(FlowCapableNode.class);
+ if (fcn == null) return;
+
+ HashMap<GroupId, GroupCtx> groupMap = new HashMap<>();
+
+ for (Group g : fcn.getGroup()) {
+ GroupCtx gctx = new GroupCtx(g.getGroupId());
+ groupMap.put(g.getGroupId(), gctx);
+
+ Buckets bs = g.getBuckets();
+ if (bs != null && bs.getBucket() != null)
+ for (Bucket b : bs.getBucket()) {
+ gctx.bucketMap.put(b.getBucketId(), new BucketCtx(b));
+ }
+ }
+
+ sync(nodeId, policyInfo, dirty, groupMap);
+
+ WriteTransaction wt = ctx.dataBroker.newWriteOnlyTransaction();
+ boolean wrote = false;
+ for (GroupCtx gctx : groupMap.values()) {
+ InstanceIdentifier<Group> giid =
+ FlowUtils.createGroupPath(nodeId, gctx.groupId);
+ if (!gctx.visited) {
+ // Remove group table
+ wrote = true;
+ wt.delete(LogicalDatastoreType.CONFIGURATION, giid);
+ } else {
+ ArrayList<Bucket> buckets = new ArrayList<>();
+
+ // update group table
+ for (BucketCtx bctx : gctx.bucketMap.values()) {
+ BucketId bid;
+ if (bctx.b != null) bid = bctx.b.getBucketId();
+ else bid = bctx.newb.getBucketId();
+ InstanceIdentifier<Bucket> biid =
+ FlowUtils.createBucketPath(nodeId,
+ gctx.groupId,
+ bid);
+ if (!bctx.visited) {
+ // remove bucket
+ LOG.info("delete {} {}", gctx.groupId, bid);
+ wrote = true;
+ wt.delete(LogicalDatastoreType.CONFIGURATION, biid);
+ } else if (bctx.b == null ||
+ !Objects.equal(bctx.newb,
+ bctx.b)) {
+ // update bucket
+ buckets.add(bctx.newb);
+ LOG.info("{} {}", gctx.groupId, bctx.newb.getBucketId());
+ }
+ if (buckets.size() > 0) {
+ GroupBuilder gb = new GroupBuilder()
+ .setGroupId(gctx.groupId)
+ .setGroupType(GroupTypes.GroupAll)
+ .setBuckets(new BucketsBuilder()
+ .setBucket(buckets)
+ .build());
+ wrote = true;
+ wt.merge(LogicalDatastoreType.CONFIGURATION,
+ giid, gb.build());
+ }
+ }
+ }
+ }
+ if (wrote)
+ Futures.addCallback(wt.submit(), updateCallback);
+ }
+
+ protected void sync(NodeId nodeId, PolicyInfo policyInfo, Dirty dirty,
+ HashMap<GroupId, GroupCtx> groupMap) throws Exception {
+
+ for (EgKey epg : ctx.epManager.getGroupsForNode(nodeId)) {
+ IndexedTenant it = ctx.policyResolver.getTenant(epg.getTenantId());
+ if (it == null) continue;
+ EndpointGroup eg = it.getEndpointGroup(epg.getEgId());
+ if (eg == null || eg.getNetworkDomain() == null) continue;
+ L2FloodDomain fd = it.resolveL2FloodDomain(eg.getNetworkDomain());
+ if (fd == null) continue;
+
+ int fdId = ctx.policyManager.getContextOrdinal(epg.getTenantId(),
+ fd.getId());
+ GroupId gid = new GroupId(Long.valueOf(fdId));
+ GroupCtx gctx = groupMap.get(gid);
+ if (gctx == null) {
+ groupMap.put(gid, gctx = new GroupCtx(gid));
+ }
+ gctx.visited = true;
+
+ // we'll use the fdId with the high bit set for remote bucket
+ // and just the local port number for local bucket
+ for (NodeId destNode : ctx.epManager.getNodesForGroup(epg)) {
+ long bucketId = (long)ctx.policyManager
+ .getContextOrdinal(destNode.getValue());
+ bucketId |= 1L << 31;
+
+ IpAddress tunDst =
+ ctx.switchManager.getTunnelIP(destNode);
+ NodeConnectorId tunPort =
+ ctx.switchManager.getTunnelPort(nodeId);
+ if (tunDst == null || tunPort == null) continue;
+ if (tunDst.getIpv4Address() != null) {
+ // XXX - TODO Add action: set tunnel dst to tunDst ipv4
+ } else if (tunDst.getIpv6Address() != null) {
+ // XXX - TODO Add action: set tunnel dst to tunDst ipv6
+ }
+
+ int epgId = ctx.policyManager
+ .getContextOrdinal(epg.getTenantId(),
+ epg.getEgId());
+
+ // TODO add action: set tunnel ID to epgId
+
+ Action output = FlowUtils.outputAction(tunPort);
+
+ BucketBuilder bb = new BucketBuilder()
+ .setBucketId(new BucketId(Long.valueOf(bucketId)))
+ .setAction(FlowUtils.writeActionList(output));
+ updateBucket(gctx, bb);
+ }
+ for (Endpoint localEp : ctx.epManager.getEPsForNode(nodeId, epg)) {
+ OfOverlayContext ofc =
+ localEp.getAugmentation(OfOverlayContext.class);
+ if (ofc == null || ofc.getNodeConnectorId() == null ||
+ (LocationType.External.equals(ofc.getLocationType())))
+ continue;
+ String cnid = ofc.getNodeConnectorId().getValue();
+ int ci = cnid.lastIndexOf(':');
+ if (ci < 0 || (ci+1 >= cnid.length()))
+ continue;
+ long bucketId;
+ try {
+ bucketId = Long.parseLong(cnid.substring(ci+1));
+ } catch (NumberFormatException e) {
+ LOG.warn("Could not parse port number {}", cnid);
+ continue;
+ }
+
+ Action output = FlowUtils.outputAction(ofc.getNodeConnectorId());
+
+ BucketBuilder bb = new BucketBuilder()
+ .setBucketId(new BucketId(Long.valueOf(bucketId)))
+ .setAction(FlowUtils.writeActionList(output));
+ updateBucket(gctx, bb);
+ }
+ }
+ }
+
+ private static void updateBucket(GroupCtx gctx, BucketBuilder bb) {
+ BucketCtx bctx = gctx.bucketMap.get(bb.getBucketId());
+ if (bctx == null) {
+ gctx.bucketMap.put(bb.getBucketId(),
+ bctx = new BucketCtx(null));
+ }
+ bctx.visited = true;
+ bctx.newb = bb.build();
+ }
+
+ private static class BucketCtx {
+ Bucket b;
+ Bucket newb;
+ boolean visited = false;
+
+ public BucketCtx(Bucket b) {
+ super();
+ this.b = b;
+ }
+ }
+
+ private static class GroupCtx {
+ GroupId groupId;
+ Map<BucketId, BucketCtx> bucketMap = new HashMap<>();
+ boolean visited = false;
+
+ public GroupCtx(GroupId groupId) {
+ super();
+ this.groupId = groupId;
+ }
+ }
+
+}
--- /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.flow;
+
+import java.util.concurrent.ScheduledExecutorService;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.EndpointManager;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.Dirty;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.SwitchManager;
+import org.opendaylight.groupbasedpolicy.resolver.PolicyInfo;
+import org.opendaylight.groupbasedpolicy.resolver.PolicyResolver;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.util.concurrent.FutureCallback;
+
+/**
+ * Manage the state of a openflow table by reacting to any events and updating
+ * the table state. This is an abstract class that must be extended for
+ * each specific table being managed.
+ * @author readams
+ */
+public abstract class OfTable {
+ protected static final Logger LOG =
+ LoggerFactory.getLogger(OfTable.class);
+
+ protected final OfTableCtx ctx;
+
+ public OfTable(OfTableCtx ctx) {
+ super();
+ this.ctx = ctx;
+ }
+
+ /**
+ * The context needed for flow tables
+ */
+ public static class OfTableCtx {
+ protected final DataBroker dataBroker;
+ protected final RpcProviderRegistry rpcRegistry;
+
+ protected final PolicyManager policyManager;
+ protected final SwitchManager switchManager;
+ protected final EndpointManager epManager;
+
+ protected final PolicyResolver policyResolver;
+
+ protected final ScheduledExecutorService executor;
+
+ public OfTableCtx(DataBroker dataBroker,
+ RpcProviderRegistry rpcRegistry,
+ PolicyManager policyManager,
+ PolicyResolver policyResolver,
+ SwitchManager switchManager,
+ EndpointManager endpointManager,
+ ScheduledExecutorService executor) {
+ super();
+ this.dataBroker = dataBroker;
+ this.rpcRegistry = rpcRegistry;
+ this.policyManager = policyManager;
+ this.switchManager = switchManager;
+ this.epManager = endpointManager;
+ this.policyResolver = policyResolver;
+ this.executor = executor;
+ }
+
+ }
+
+ // *******
+ // OfTable
+ // *******
+
+ /**
+ * Update the relevant flow table for the node
+ * @param nodeId the node to update
+ * @param dirty the dirty set
+ * @throws Exception
+ */
+ public abstract void update(NodeId nodeId,
+ PolicyInfo policyInfo,
+ Dirty dirty) throws Exception;
+
+ // ***************
+ // Utility methods
+ // ***************
+
+
+ /**
+ * Generic callback for handling result of flow manipulation
+ * @author readams
+ *
+ * @param <T> the expected output type
+ */
+ protected static class OfCallback<T> implements FutureCallback<T> {
+ @Override
+ public void onSuccess(T result) {
+ }
+
+ @Override
+ public void onFailure(Throwable t) {
+ LOG.error("Failed to add flow entry", t);
+ }
+ }
+ protected static final OfCallback<Void> updateCallback =
+ new OfCallback<>();
+
+
+}
public static final short TABLE_ID = 3;
- public PolicyEnforcer(FlowTableCtx ctx) {
+ public PolicyEnforcer(OfTable.OfTableCtx ctx) {
super(ctx);
}
dropFlow(t, tiid, flowMap, Integer.valueOf(1), null);
HashSet<CgPair> visitedPairs = new HashSet<>();
- HashSet<EgKey> visitedEgs = new HashSet<>();
- for (Endpoint src : ctx.epManager.getEndpointsForNode(nodeId)) {
- if (src.getTenant() == null || src.getEndpointGroup() == null)
- continue;
- List<ConditionName> conds =
- ctx.epManager.getCondsForEndpoint(src);
- ConditionGroup scg =
- policyInfo.getEgCondGroup(new EgKey(src.getTenant(),
- src.getEndpointGroup()),
- conds);
+ for (EgKey sepg : ctx.epManager.getGroupsForNode(nodeId)) {
+ // Allow traffic within the same endpoint group if the policy
+ // specifies
+ IndexedTenant tenant =
+ ctx.policyResolver.getTenant(sepg.getTenantId());
+ EndpointGroup group =
+ tenant.getEndpointGroup(sepg.getEgId());
+ IntraGroupPolicy igp = group.getIntraGroupPolicy();
int sepgId =
- ctx.policyManager.getContextOrdinal(src.getTenant(),
- src.getEndpointGroup());
- int scgId = ctx.policyManager.getConfGroupOrdinal(scg);
-
- EgKey sepg = new EgKey(src.getTenant(), src.getEndpointGroup());
-
- if (!visitedEgs.contains(sepg)) {
- visitedEgs.add(sepg);
- IndexedTenant tenant =
- ctx.policyResolver.getTenant(sepg.getTenantId());
- EndpointGroup group =
- tenant.getEndpointGroup(sepg.getEgId());
- IntraGroupPolicy igp = group.getIntraGroupPolicy();
- if (igp == null || igp.equals(IntraGroupPolicy.Allow)) {
- allowSameEpg(t, tiid, flowMap, nodeId, sepgId);
- }
+ ctx.policyManager.getContextOrdinal(sepg.getTenantId(),
+ sepg.getEgId());
+ if (igp == null || igp.equals(IntraGroupPolicy.Allow)) {
+ allowSameEpg(t, tiid, flowMap, nodeId, sepgId);
}
-
- Set<EgKey> peers = policyInfo.getPeers(sepg);
- for (EgKey depg : peers) {
- int depgId =
- ctx.policyManager.getContextOrdinal(depg.getTenantId(),
- depg.getEgId());
-
- for (Endpoint dst : ctx.epManager.getEndpointsForGroup(depg)) {
- conds = ctx.epManager.getCondsForEndpoint(src);
- ConditionGroup dcg =
- policyInfo.getEgCondGroup(new EgKey(dst.getTenant(),
- dst.getEndpointGroup()),
- conds);
- int dcgId = ctx.policyManager.getConfGroupOrdinal(dcg);
-
- CgPair p = new CgPair(depgId, sepgId, dcgId, scgId);
- if (visitedPairs.contains(p)) continue;
- visitedPairs.add(p);
- syncPolicy(t, tiid, flowMap, nodeId, policyInfo,
- p, depg, sepg, dcg, scg);
-
- p = new CgPair(sepgId, depgId, scgId, dcgId);
- if (visitedPairs.contains(p)) continue;
- visitedPairs.add(p);
- syncPolicy(t, tiid, flowMap, nodeId, policyInfo,
- p, sepg, depg, scg, dcg);
-
+ for (Endpoint src : ctx.epManager.getEPsForNode(nodeId, sepg)) {
+ if (src.getTenant() == null || src.getEndpointGroup() == null)
+ continue;
+
+ List<ConditionName> conds =
+ ctx.epManager.getCondsForEndpoint(src);
+ ConditionGroup scg = policyInfo.getEgCondGroup(sepg, conds);
+ int scgId = ctx.policyManager.getConfGroupOrdinal(scg);
+
+ Set<EgKey> peers = policyInfo.getPeers(sepg);
+ for (EgKey depg : peers) {
+ int depgId =
+ ctx.policyManager.getContextOrdinal(depg.getTenantId(),
+ depg.getEgId());
+
+ for (Endpoint dst : ctx.epManager.getEndpointsForGroup(depg)) {
+
+ conds = ctx.epManager.getCondsForEndpoint(src);
+ ConditionGroup dcg =
+ policyInfo.getEgCondGroup(new EgKey(dst.getTenant(),
+ dst.getEndpointGroup()),
+ conds);
+ int dcgId = ctx.policyManager.getConfGroupOrdinal(dcg);
+
+ CgPair p = new CgPair(depgId, sepgId, dcgId, scgId);
+ if (visitedPairs.contains(p)) continue;
+ visitedPairs.add(p);
+ syncPolicy(t, tiid, flowMap, nodeId, policyInfo,
+ p, depg, sepg, dcg, scg);
+
+ p = new CgPair(sepgId, depgId, scgId, dcgId);
+ if (visitedPairs.contains(p)) continue;
+ visitedPairs.add(p);
+ syncPolicy(t, tiid, flowMap, nodeId, policyInfo,
+ p, sepg, depg, scg, dcg);
+
+ }
}
}
}
import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.Dirty;
+import org.opendaylight.groupbasedpolicy.resolver.EgKey;
import org.opendaylight.groupbasedpolicy.resolver.PolicyInfo;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
public static final short TABLE_ID = 0;
- public PortSecurity(FlowTableCtx ctx) {
+ public PortSecurity(OfTable.OfTableCtx ctx) {
super(ctx);
}
dropFlow(t, tiid, flowMap, 111, FlowUtils.IPv4);
dropFlow(t, tiid, flowMap, 112, FlowUtils.IPv6);
- for (Endpoint e : ctx.epManager.getEndpointsForNode(nodeId)) {
- OfOverlayContext ofc = e.getAugmentation(OfOverlayContext.class);
- if (ofc != null && ofc.getNodeConnectorId() != null &&
- (ofc.getLocationType() == null ||
- LocationType.Internal.equals(ofc.getLocationType()))) {
- // Allow layer 3 traffic (ARP and IP) with the correct source
- // IP, MAC, and source port
- l3flow(t, tiid, flowMap, e, ofc, 120, false);
- l3flow(t, tiid, flowMap, e, ofc, 121, true);
-
- // Allow layer 2 traffic with the correct source MAC and
- // source port (note lower priority than drop IP rules)
- l2flow(t, tiid, flowMap, e, ofc, 100);
+ for (EgKey sepg : ctx.epManager.getGroupsForNode(nodeId)) {
+ for (Endpoint e : ctx.epManager.getEPsForNode(nodeId, sepg)) {
+ OfOverlayContext ofc = e.getAugmentation(OfOverlayContext.class);
+ if (ofc != null && ofc.getNodeConnectorId() != null &&
+ (ofc.getLocationType() == null ||
+ LocationType.Internal.equals(ofc.getLocationType()))) {
+ // Allow layer 3 traffic (ARP and IP) with the correct
+ // source IP, MAC, and source port
+ l3flow(t, tiid, flowMap, e, ofc, 120, false);
+ l3flow(t, tiid, flowMap, e, ofc, 121, true);
+
+ // Allow layer 2 traffic with the correct source MAC and
+ // source port (note lower priority than drop IP rules)
+ l2flow(t, tiid, flowMap, e, ofc, 100);
+ }
}
}
}
public static final short TABLE_ID = 1;
- public SourceMapper(FlowTableCtx ctx) {
+ public SourceMapper(OfTable.OfTableCtx ctx) {
super(ctx);
}
dropFlow(t, tiid, flowMap, Integer.valueOf(1), null);
// XXX TODO Set sEPG from tunnel ports using the tunnel ID
-
- for (Endpoint e : ctx.epManager.getEndpointsForNode(nodeId)) {
- OfOverlayContext ofc = e.getAugmentation(OfOverlayContext.class);
- if (ofc != null && ofc.getNodeConnectorId() != null &&
- (ofc.getLocationType() == null ||
- LocationType.Internal.equals(ofc.getLocationType())) &&
- e.getTenant() != null && e.getEndpointGroup() != null) {
- syncEP(t, tiid, flowMap, policyInfo, nodeId, e, ofc);
- }
+
+ for (EgKey sepg : ctx.epManager.getGroupsForNode(nodeId)) {
+ for (Endpoint e : ctx.epManager.getEPsForNode(nodeId, sepg)) {
+ OfOverlayContext ofc = e.getAugmentation(OfOverlayContext.class);
+ if (ofc != null && ofc.getNodeConnectorId() != null &&
+ (ofc.getLocationType() == null ||
+ LocationType.Internal.equals(ofc.getLocationType())) &&
+ e.getTenant() != null && e.getEndpointGroup() != null) {
+ syncEP(t, tiid, flowMap, policyInfo, nodeId, e, ofc);
+ }
+ }
}
}
+++ /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.resolver;
-
-import java.util.Collection;
-import java.util.List;
-
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
-
-/**
- * When the policy changes, recompute the set of active condition groups
- * based on the endpoints in a particular endpoint group
- * @author readams
- */
-public interface EndpointProvider {
- /**
- * Get a collection of endpoints in a particular endpoint group
- * @param nodeId the nodeId of the switch to get endpoints for
- * @return a collection of {@link Endpoint} objects.
- */
- public Collection<Endpoint> getEndpointsForGroup(EgKey eg);
-
- /**
- * Get the effective list of conditions that apply to a particular
- * endpoint. This could include additional conditions over the condition
- * labels directly represented in the endpoint object
- * @param endpoint the {@link Endpoint} to resolve
- * @return the list of {@link ConditionName}
- */
- public List<ConditionName> getCondsForEndpoint(Endpoint endpoint);
-}
import static org.mockito.Mockito.*;
-public class DestinationMapperTest extends FlowTableTest {
+public class DestinationMapperTest extends OfTableTest {
protected static final Logger LOG =
LoggerFactory.getLogger(DestinationMapperTest.class);
ReadWriteTransaction t = dosync(null);
verify(t, times(1)).put(any(LogicalDatastoreType.class),
Matchers.<InstanceIdentifier<Flow>>any(),
- any(Flow.class));
+ any(Flow.class), anyBoolean());
}
private void verifyDMap(Endpoint remoteEp,
ArgumentCaptor<Flow> ac = ArgumentCaptor.forClass(Flow.class);
verify(t, atLeastOnce()).put(eq(LogicalDatastoreType.CONFIGURATION),
Matchers.<InstanceIdentifier<Flow>>any(),
- ac.capture());
+ ac.capture(), anyBoolean());
int count = 0;
HashMap<String, FlowCtx> flowMap = new HashMap<>();
t = dosync(flowMap);
verify(t, never()).put(any(LogicalDatastoreType.class),
Matchers.<InstanceIdentifier<Flow>>any(),
- any(Flow.class));
+ any(Flow.class), anyBoolean());
}
@Override
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.MockPolicyManager;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.MockSwitchManager;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowTable.FlowCtx;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowTable.FlowTableCtx;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OfTable.OfTableCtx;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.L4Classifier;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.SubjectFeatures;
import org.opendaylight.groupbasedpolicy.resolver.MockPolicyResolver;
import static org.mockito.Mockito.*;
-public class FlowTableTest {
- FlowTableCtx ctx;
+public class OfTableTest {
+ OfTableCtx ctx;
FlowTable table;
MockEndpointManager endpointManager;
policyManager = new MockPolicyManager(policyResolver, endpointManager);
switchManager = new MockSwitchManager();
- ctx = new FlowTableCtx(null,
- null,
- policyManager,
- policyResolver,
- switchManager,
- endpointManager,
- null);
+ ctx = new OfTableCtx(null,
+ null,
+ policyManager,
+ policyResolver,
+ switchManager,
+ endpointManager,
+ null);
}
protected void setup() throws Exception {
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
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.classifier.refs.ClassifierRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRefBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.TenantBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatch;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.mockito.Mockito.*;
-public class PolicyEnforcerTest extends FlowTableTest {
+public class PolicyEnforcerTest extends OfTableTest {
protected static final Logger LOG =
LoggerFactory.getLogger(PolicyEnforcerTest.class);
ReadWriteTransaction t = dosync(null);
verify(t, times(1)).put(any(LogicalDatastoreType.class),
Matchers.<InstanceIdentifier<Flow>>any(),
- any(Flow.class));
+ any(Flow.class), anyBoolean());
}
@Test
ArgumentCaptor<Flow> ac = ArgumentCaptor.forClass(Flow.class);
verify(t, atLeastOnce()).put(eq(LogicalDatastoreType.CONFIGURATION),
Matchers.<InstanceIdentifier<Flow>>any(),
- ac.capture());
+ ac.capture(), anyBoolean());
int count = 0;
HashMap<String, FlowCtx> flowMap = new HashMap<>();
for (Flow f : ac.getAllValues()) {
t = dosync(flowMap);
verify(t, never()).put(any(LogicalDatastoreType.class),
Matchers.<InstanceIdentifier<Flow>>any(),
- any(Flow.class));
+ any(Flow.class), anyBoolean());
}
@Test
ArgumentCaptor<Flow> ac = ArgumentCaptor.forClass(Flow.class);
verify(t, atLeastOnce()).put(eq(LogicalDatastoreType.CONFIGURATION),
Matchers.<InstanceIdentifier<Flow>>any(),
- ac.capture());
+ ac.capture(), anyBoolean());
int count = 0;
HashMap<String, FlowCtx> flowMap = new HashMap<>();
for (Flow f : ac.getAllValues()) {
t = dosync(flowMap);
verify(t, never()).put(any(LogicalDatastoreType.class),
Matchers.<InstanceIdentifier<Flow>>any(),
- any(Flow.class));
+ any(Flow.class), anyBoolean());
}
@Test
import static org.mockito.Mockito.*;
-public class PortSecurityTest extends FlowTableTest {
+public class PortSecurityTest extends OfTableTest {
protected static final Logger LOG =
LoggerFactory.getLogger(PortSecurityTest.class);
ArgumentCaptor<Flow> ac = ArgumentCaptor.forClass(Flow.class);
verify(t, times(4)).put(eq(LogicalDatastoreType.CONFIGURATION),
Matchers.<InstanceIdentifier<Flow>>any(),
- ac.capture());
+ ac.capture(), anyBoolean());
int count = 0;
HashMap<String, FlowCtx> flowMap = new HashMap<>();
t = dosync(flowMap);
verify(t, never()).put(any(LogicalDatastoreType.class),
Matchers.<InstanceIdentifier<Flow>>any(),
- any(Flow.class));
+ any(Flow.class), anyBoolean());
}
@Test
ArgumentCaptor<Flow> ac = ArgumentCaptor.forClass(Flow.class);
verify(t, atLeastOnce()).put(eq(LogicalDatastoreType.CONFIGURATION),
Matchers.<InstanceIdentifier<Flow>>any(),
- ac.capture());
+ ac.capture(), anyBoolean());
int count = 0;
HashMap<String, FlowCtx> flowMap = new HashMap<>();
t = dosync(flowMap);
verify(t, never()).put(any(LogicalDatastoreType.class),
Matchers.<InstanceIdentifier<Flow>>any(),
- any(Flow.class));
+ any(Flow.class), anyBoolean());
}
@Test
ArgumentCaptor<Flow> ac = ArgumentCaptor.forClass(Flow.class);
verify(t, atLeastOnce()).put(eq(LogicalDatastoreType.CONFIGURATION),
Matchers.<InstanceIdentifier<Flow>>any(),
- ac.capture());
+ ac.capture(), anyBoolean());
int count = 0;
HashMap<String, FlowCtx> flowMap = new HashMap<>();
t = dosync(flowMap);
verify(t, never()).put(any(LogicalDatastoreType.class),
Matchers.<InstanceIdentifier<Flow>>any(),
- any(Flow.class));
+ any(Flow.class), anyBoolean());
}
@Test
ArgumentCaptor<Flow> ac = ArgumentCaptor.forClass(Flow.class);
verify(t, atLeastOnce()).put(eq(LogicalDatastoreType.CONFIGURATION),
Matchers.<InstanceIdentifier<Flow>>any(),
- ac.capture());
+ ac.capture(), anyBoolean());
int count = 0;
HashMap<String, FlowCtx> flowMap = new HashMap<>();
t = dosync(flowMap);
verify(t, never()).put(any(LogicalDatastoreType.class),
Matchers.<InstanceIdentifier<Flow>>any(),
- any(Flow.class));
+ any(Flow.class), anyBoolean());
}
}
import static org.mockito.Mockito.*;
-public class SourceMapperTest extends FlowTableTest {
+public class SourceMapperTest extends OfTableTest {
protected static final Logger LOG =
LoggerFactory.getLogger(SourceMapperTest.class);
@Before
ReadWriteTransaction t = dosync(null);
verify(t, times(1)).put(any(LogicalDatastoreType.class),
Matchers.<InstanceIdentifier<Flow>>any(),
- any(Flow.class));
+ any(Flow.class), anyBoolean());
}
@Test
ArgumentCaptor<Flow> ac = ArgumentCaptor.forClass(Flow.class);
verify(t, times(2)).put(eq(LogicalDatastoreType.CONFIGURATION),
Matchers.<InstanceIdentifier<Flow>>any(),
- ac.capture());
+ ac.capture(), anyBoolean());
int count = 0;
HashMap<String, FlowCtx> flowMap = new HashMap<>();
t = dosync(flowMap);
verify(t, never()).put(any(LogicalDatastoreType.class),
Matchers.<InstanceIdentifier<Flow>>any(),
- any(Flow.class));
+ any(Flow.class), anyBoolean());
}
}