2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
11 import java.util.Collections;
12 import java.util.HashMap;
13 import java.util.HashSet;
14 import java.util.List;
18 import javax.annotation.concurrent.Immutable;
20 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
21 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.Dirty;
22 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.RegMatch;
23 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.Classifier;
24 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.SubjectFeatures;
25 import org.opendaylight.groupbasedpolicy.resolver.ConditionGroup;
26 import org.opendaylight.groupbasedpolicy.resolver.EgKey;
27 import org.opendaylight.groupbasedpolicy.resolver.IndexedTenant;
28 import org.opendaylight.groupbasedpolicy.resolver.Policy;
29 import org.opendaylight.groupbasedpolicy.resolver.PolicyInfo;
30 import org.opendaylight.groupbasedpolicy.resolver.RuleGroup;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRef;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup.IntraGroupPolicy;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.subject.Rule;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ClassifierInstance;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg0;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg1;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg2;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg3;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg7;
53 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
57 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.*;
60 * Manage the table that enforces policy on the traffic. Traffic is denied
61 * unless specifically allowed by policy
64 public class PolicyEnforcer extends FlowTable {
65 protected static final Logger LOG =
66 LoggerFactory.getLogger(PolicyEnforcer.class);
68 public static final short TABLE_ID = 3;
70 public PolicyEnforcer(OfTable.OfTableCtx ctx) {
75 public short getTableId() {
80 public void sync(ReadWriteTransaction t, InstanceIdentifier<Table> tiid,
81 Map<String, FlowCtx> flowMap, NodeId nodeId,
82 PolicyInfo policyInfo, Dirty dirty)
84 dropFlow(t, tiid, flowMap, Integer.valueOf(1), null);
85 allowFromTunnel(t, tiid, flowMap, nodeId);
87 HashSet<CgPair> visitedPairs = new HashSet<>();
89 for (EgKey sepg : ctx.epManager.getGroupsForNode(nodeId)) {
90 // Allow traffic within the same endpoint group if the policy
92 IndexedTenant tenant =
93 ctx.policyResolver.getTenant(sepg.getTenantId());
95 tenant.getEndpointGroup(sepg.getEgId());
96 IntraGroupPolicy igp = group.getIntraGroupPolicy();
98 ctx.policyManager.getContextOrdinal(sepg.getTenantId(),
100 if (igp == null || igp.equals(IntraGroupPolicy.Allow)) {
101 allowSameEpg(t, tiid, flowMap, nodeId, sepgId);
104 for (Endpoint src : ctx.epManager.getEPsForNode(nodeId, sepg)) {
105 if (src.getTenant() == null || src.getEndpointGroup() == null)
108 List<ConditionName> conds =
109 ctx.epManager.getCondsForEndpoint(src);
110 ConditionGroup scg = policyInfo.getEgCondGroup(sepg, conds);
111 int scgId = ctx.policyManager.getCondGroupOrdinal(scg);
113 Set<EgKey> peers = policyInfo.getPeers(sepg);
114 for (EgKey depg : peers) {
116 ctx.policyManager.getContextOrdinal(depg.getTenantId(),
119 for (Endpoint dst : ctx.epManager.getEndpointsForGroup(depg)) {
121 conds = ctx.epManager.getCondsForEndpoint(dst);
123 policyInfo.getEgCondGroup(new EgKey(dst.getTenant(),
124 dst.getEndpointGroup()),
126 int dcgId = ctx.policyManager.getCondGroupOrdinal(dcg);
128 CgPair p = new CgPair(depgId, sepgId, dcgId, scgId);
129 if (visitedPairs.contains(p)) continue;
131 syncPolicy(t, tiid, flowMap, nodeId, policyInfo,
132 p, depg, sepg, dcg, scg);
134 p = new CgPair(sepgId, depgId, scgId, dcgId);
135 if (visitedPairs.contains(p)) continue;
137 syncPolicy(t, tiid, flowMap, nodeId, policyInfo,
138 p, sepg, depg, scg, dcg);
146 private void allowSameEpg(ReadWriteTransaction t,
147 InstanceIdentifier<Table> tiid,
148 Map<String, FlowCtx> flowMap, NodeId nodeId,
150 FlowId flowId = new FlowId(new StringBuilder()
151 .append("intraallow|")
152 .append(sepgId).toString());
153 if (visit(flowMap, flowId.getValue())) {
154 MatchBuilder mb = new MatchBuilder();
156 RegMatch.of(NxmNxReg0.class,Long.valueOf(sepgId)),
157 RegMatch.of(NxmNxReg2.class,Long.valueOf(sepgId)));
158 FlowBuilder flow = base()
160 .setMatch(mb.build())
162 .setInstructions(instructions(applyActionIns(nxOutputRegAction(NxmNxReg7.class))));
163 writeFlow(t, tiid, flow.build());
167 private void allowFromTunnel(ReadWriteTransaction t,
168 InstanceIdentifier<Table> tiid,
169 Map<String, FlowCtx> flowMap, NodeId nodeId) {
170 NodeConnectorId tunPort =
171 ctx.switchManager.getTunnelPort(nodeId);
172 if (tunPort == null) return;
174 FlowId flowId = new FlowId("tunnelallow");
175 if (visit(flowMap, flowId.getValue())) {
176 MatchBuilder mb = new MatchBuilder()
179 RegMatch.of(NxmNxReg1.class,Long.valueOf(0xffffff)));
180 FlowBuilder flow = base()
182 .setMatch(mb.build())
184 .setInstructions(instructions(applyActionIns(nxOutputRegAction(NxmNxReg7.class))));
185 writeFlow(t, tiid, flow.build());
189 private void syncPolicy(ReadWriteTransaction t,
190 InstanceIdentifier<Table> tiid,
191 Map<String, FlowCtx> flowMap, NodeId nodeId,
192 PolicyInfo policyInfo,
193 CgPair p, EgKey sepg, EgKey depg,
194 ConditionGroup scg, ConditionGroup dcg)
196 // XXX - TODO raise an exception for rules between the same
197 // endpoint group that are asymmetric
198 Policy policy = policyInfo.getPolicy(sepg, depg);
199 List<RuleGroup> rgs = policy.getRules(scg, dcg);
201 int priority = 65000;
202 for (RuleGroup rg : rgs) {
203 TenantId tenantId = rg.getContractTenant().getId();
204 IndexedTenant tenant = ctx.policyResolver.getTenant(tenantId);
205 for (Rule r : rg.getRules()) {
206 syncDirection(t, tiid, flowMap, nodeId, tenant,
207 p, r, Direction.In, priority);
208 syncDirection(t, tiid, flowMap, nodeId, tenant,
209 p, r, Direction.Out, priority);
216 private void syncDirection(ReadWriteTransaction t,
217 InstanceIdentifier<Table> tiid,
218 Map<String, FlowCtx> flowMap, NodeId nodeId,
219 IndexedTenant contractTenant,
220 CgPair p, Rule r, Direction d, int priority) {
221 for (ClassifierRef cr : r.getClassifierRef()) {
222 if (cr.getDirection() != null &&
223 !cr.getDirection().equals(Direction.Bidirectional) &&
224 !cr.getDirection().equals(d))
227 StringBuilder idb = new StringBuilder();
228 // XXX - TODO - implement connection tracking (requires openflow
229 // extension and data plane support)
231 MatchBuilder baseMatch = new MatchBuilder();
233 if (d.equals(Direction.In)) {
243 addNxRegMatch(baseMatch,
244 RegMatch.of(NxmNxReg0.class,Long.valueOf(p.sepg)),
245 RegMatch.of(NxmNxReg1.class,Long.valueOf(p.scgId)),
246 RegMatch.of(NxmNxReg2.class,Long.valueOf(p.depg)),
247 RegMatch.of(NxmNxReg3.class,Long.valueOf(p.dcgId)));
258 addNxRegMatch(baseMatch,
259 RegMatch.of(NxmNxReg0.class,Long.valueOf(p.depg)),
260 RegMatch.of(NxmNxReg1.class,Long.valueOf(p.dcgId)),
261 RegMatch.of(NxmNxReg2.class,Long.valueOf(p.sepg)),
262 RegMatch.of(NxmNxReg3.class,Long.valueOf(p.scgId)));
266 ClassifierInstance ci = contractTenant.getClassifier(cr.getName());
268 // XXX TODO fail the match and raise an exception
269 LOG.warn("Classifier instance {} not found",
270 cr.getName().getValue());
273 Classifier cfier = SubjectFeatures
274 .getClassifier(ci.getClassifierDefinitionId());
276 // XXX TODO fail the match and raise an exception
277 LOG.warn("Classifier definition {} not found",
278 ci.getClassifierDefinitionId().getValue());
282 List<MatchBuilder> matches = Collections.singletonList(baseMatch);
283 Map<String,Object> params = new HashMap<>();
284 for (ParameterValue v : ci.getParameterValue()) {
285 if (v.getName() == null) continue;
286 if (v.getIntValue() != null) {
287 params.put(v.getName().getValue(), v.getIntValue());
288 } else if (v.getStringValue() != null) {
289 params.put(v.getName().getValue(), v.getStringValue());
293 matches = cfier.updateMatch(matches, params);
294 String baseId = idb.toString();
295 FlowBuilder flow = base()
296 .setPriority(Integer.valueOf(priority));
297 for (MatchBuilder match : matches) {
298 Match m = match.build();
299 FlowId flowId = new FlowId(baseId + "|" + m.toString());
300 if (visit(flowMap, flowId.getValue())) {
303 .setPriority(Integer.valueOf(priority))
304 .setInstructions(instructions(applyActionIns(nxOutputRegAction(NxmNxReg7.class))));
305 writeFlow(t, tiid, flow.build());
313 private static class CgPair {
314 private final int sepg;
315 private final int depg;
316 private final int scgId;
317 private final int dcgId;
319 public CgPair(int sepg, int depg, int scgId, int dcgId) {
328 public int hashCode() {
329 final int prime = 31;
331 result = prime * result + dcgId;
332 result = prime * result + depg;
333 result = prime * result + scgId;
334 result = prime * result + sepg;
339 public boolean equals(Object obj) {
344 if (getClass() != obj.getClass())
346 CgPair other = (CgPair) obj;
347 if (dcgId != other.dcgId)
349 if (depg != other.depg)
351 if (scgId != other.scgId)
353 if (sepg != other.sepg)