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 static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.addNxRegMatch;
12 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.applyActionIns;
13 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.gotoTableIns;
14 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.instructions;
15 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxOutputRegAction;
17 import java.util.ArrayList;
18 import java.util.Collections;
19 import java.util.Comparator;
20 import java.util.HashMap;
21 import java.util.HashSet;
22 import java.util.List;
26 import javax.annotation.concurrent.Immutable;
28 import org.opendaylight.groupbasedpolicy.sf.actions.AllowActionDefinition;
29 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfWriter;
30 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
31 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.RegMatch;
32 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OrdinalFactory.EndpointFwdCtxOrdinals;
33 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.Action;
34 //import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.AllowAction;
35 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.ClassificationResult;
36 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.Classifier;
37 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.ParamDerivator;
38 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.SubjectFeatures;
39 import org.opendaylight.groupbasedpolicy.resolver.EgKey;
40 import org.opendaylight.groupbasedpolicy.resolver.EndpointConstraint;
41 import org.opendaylight.groupbasedpolicy.resolver.IndexedTenant;
42 import org.opendaylight.groupbasedpolicy.resolver.Policy;
43 import org.opendaylight.groupbasedpolicy.resolver.PolicyInfo;
44 import org.opendaylight.groupbasedpolicy.resolver.RuleGroup;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.action.refs.ActionRef;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRef;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup.IntraGroupPolicy;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.subject.Rule;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ActionInstance;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ClassifierInstance;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg0;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg1;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg2;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg3;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg5;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg7;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeVxlan;
78 import org.slf4j.Logger;
79 import org.slf4j.LoggerFactory;
81 import com.google.common.base.Preconditions;
82 import com.google.common.collect.ComparisonChain;
83 import com.google.common.collect.Ordering;
84 import com.google.common.collect.Table.Cell;
87 * Manage the table that enforces policy on the traffic. Traffic is denied
88 * unless specifically allowed by policy
90 public class PolicyEnforcer extends FlowTable {
92 protected static final Logger LOG = LoggerFactory.getLogger(PolicyEnforcer.class);
94 private static org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction gotoEgressNatInstruction;
95 private static org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction gotoExternalInstruction;
97 public static short TABLE_ID;
99 public PolicyEnforcer(OfContext ctx, short tableId) {
101 PolicyEnforcer.TABLE_ID = tableId;
102 PolicyEnforcer.gotoEgressNatInstruction = gotoTableIns(ctx.getPolicyManager().getTABLEID_EGRESS_NAT());
103 PolicyEnforcer.gotoExternalInstruction = gotoTableIns(ctx.getPolicyManager().getTABLEID_EXTERNAL_MAPPER());
107 public short getTableId() {
112 public void sync(NodeId nodeId, PolicyInfo policyInfo, OfWriter ofWriter) throws Exception {
114 ofWriter.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(1), null, TABLE_ID));
116 NodeConnectorId tunPort = ctx.getSwitchManager().getTunnelPort(nodeId, TunnelTypeVxlan.class);
117 if (tunPort != null) {
118 ofWriter.writeFlow(nodeId, TABLE_ID, allowFromTunnel(tunPort));
121 HashSet<PolicyPair> visitedPairs = new HashSet<>();
122 HashSet<PolicyPair> visitedReversePairs = new HashSet<>();
124 // Used for ARP flows
125 Set<Integer> fdIds = new HashSet<>();
127 for (Endpoint srcEp : ctx.getEndpointManager().getEndpointsForNode(nodeId)) {
128 for (EgKey srcEpgKey : ctx.getEndpointManager().getEgKeysForEndpoint(srcEp)) {
129 Set<EgKey> peers = policyInfo.getPeers(srcEpgKey);
130 for (EgKey dstEpgKey : peers) {
131 Set<Endpoint> dstEndpoints = new HashSet<>();
132 dstEndpoints.addAll(ctx.getEndpointManager().getEndpointsForGroup(dstEpgKey));
133 dstEndpoints.addAll(ctx.getEndpointManager().getExtEpsNoLocForGroup(dstEpgKey));
134 for (Endpoint dstEp : dstEndpoints) {
136 EndpointFwdCtxOrdinals srcEpFwdCxtOrds = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx,
138 if (srcEpFwdCxtOrds == null) {
139 LOG.debug("getEndpointFwdCtxOrdinals is null for EP {}", srcEp);
143 EndpointFwdCtxOrdinals dstEpFwdCxtOrds = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx,
145 if (dstEpFwdCxtOrds == null) {
146 LOG.debug("getEndpointFwdCtxOrdinals is null for EP {}", dstEp);
150 int dcgId = dstEpFwdCxtOrds.getCgId();
151 int depgId = dstEpFwdCxtOrds.getEpgId();
152 int scgId = srcEpFwdCxtOrds.getCgId();
153 int sepgId = srcEpFwdCxtOrds.getEpgId();
155 fdIds.add(srcEpFwdCxtOrds.getFdId());
156 NetworkElements netElements = new NetworkElements(srcEp, dstEp, nodeId, ctx, policyInfo);
158 Policy policy = policyInfo.getPolicy(dstEpgKey, srcEpgKey);
159 for (Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>> activeRulesByConstraints : getActiveRulesBetweenEps(
160 policy, dstEp, srcEp)) {
161 Set<IpPrefix> sIpPrefixes = Policy.getIpPrefixesFrom(activeRulesByConstraints.getRowKey()
163 Set<IpPrefix> dIpPrefixes = Policy.getIpPrefixesFrom(activeRulesByConstraints.getColumnKey()
165 PolicyPair policyPair = new PolicyPair(depgId, sepgId, dcgId, scgId, dIpPrefixes,
166 sIpPrefixes, netElements.getDstNodeId(), netElements.getSrcNodeId());
167 if (visitedPairs.contains(policyPair)) {
168 LOG.trace("PolicyEnforcer: Already visited PolicyPair {}, endpoints {} {} skipped",
169 policyPair, srcEp.getKey(), dstEp.getKey());
172 LOG.trace("PolicyEnforcer: Visiting PolicyPair {} endpoints {} {}", policyPair,
173 srcEp.getKey(), dstEp.getKey());
174 visitedPairs.add(policyPair);
176 syncPolicy(ofWriter, netElements, activeRulesByConstraints.getValue(), policyPair);
180 policy = policyInfo.getPolicy(srcEpgKey, dstEpgKey);
181 for (Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>> activeRulesByConstraints : getActiveRulesBetweenEps(
182 policy, srcEp, dstEp)) {
183 Set<IpPrefix> sIpPrefixes = Policy.getIpPrefixesFrom(activeRulesByConstraints.getRowKey()
185 Set<IpPrefix> dIpPrefixes = Policy.getIpPrefixesFrom(activeRulesByConstraints.getColumnKey()
187 PolicyPair policyPair = new PolicyPair(sepgId, depgId, scgId, dcgId, sIpPrefixes,
188 dIpPrefixes, netElements.getSrcNodeId(), netElements.getDstNodeId());
189 if (visitedReversePairs.contains(policyPair)) {
191 "PolicyEnforcer: Reverse: Already visited PolicyPair {}, endpoints {} {} skipped",
192 policyPair, srcEp.getKey(), dstEp.getKey());
195 LOG.trace("PolicyEnforcer: Reverse: Visiting: PolicyPair {} via endpoints {} {}",
196 policyPair, srcEp.getKey(), dstEp.getKey());
197 visitedReversePairs.add(policyPair);
200 syncPolicy(ofWriter, netElements, activeRulesByConstraints.getValue(), policyPair);
208 for (Endpoint srcEp : ctx.getEndpointManager().getEndpointsForNode(nodeId)) {
209 for (EgKey srcEpgKey : ctx.getEndpointManager().getEgKeysForEndpoint(srcEp)) {
211 IndexedTenant tenant = ctx.getPolicyResolver().getTenant(srcEpgKey.getTenantId());
212 if (tenant != null) {
213 EndpointGroup group = tenant.getEndpointGroup(srcEpgKey.getEgId());
215 LOG.debug("EPG {} does not exit and is used in EP {}", srcEpgKey, srcEp.getKey());
218 IntraGroupPolicy igp = group.getIntraGroupPolicy();
220 if (igp == null || igp.equals(IntraGroupPolicy.Allow)) {
221 for (Endpoint dstEp : ctx.getEndpointManager().getEndpointsForGroup(srcEpgKey)) {
222 EndpointFwdCtxOrdinals srcEpFwdCxtOrds =
223 OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, policyInfo, srcEp);
224 if (srcEpFwdCxtOrds == null) {
225 LOG.debug("getEndpointFwdCtxOrdinals is null for EP {}", srcEp);
229 EndpointFwdCtxOrdinals dstEpFwdCxtOrds =
230 OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, policyInfo, dstEp);
231 if (dstEpFwdCxtOrds == null) {
232 LOG.debug("getEndpointFwdCtxOrdinals is null for EP {}", dstEp);
236 int depgId = dstEpFwdCxtOrds.getEpgId();
237 int sepgId = srcEpFwdCxtOrds.getEpgId();
238 ofWriter.writeFlow(nodeId, TABLE_ID, allowSameEpg(sepgId, depgId));
239 ofWriter.writeFlow(nodeId, TABLE_ID, allowSameEpg(depgId, sepgId));
246 // Write ARP flows per flood domain.
247 for (Integer fdId : fdIds) {
248 ofWriter.writeFlow(nodeId, TABLE_ID, createArpFlow(fdId));
252 private Flow createArpFlow(Integer fdId) {
254 Long etherType = FlowUtils.ARP;
255 // L2 Classifier so 20,000 for now
256 Integer priority = 20000;
258 MatchBuilder mb = new MatchBuilder().setEthernetMatch(FlowUtils.ethernetMatch(null, null, etherType));
260 addNxRegMatch(mb, RegMatch.of(NxmNxReg5.class, Long.valueOf(fdId)));
262 Match match = mb.build();
263 FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "arp", match);
264 Flow flow = base().setPriority(priority)
267 .setInstructions(instructions(applyActionIns(nxOutputRegAction(NxmNxReg7.class))))
272 private Flow allowSameEpg(int sepgId, int depgId) {
274 MatchBuilder mb = new MatchBuilder();
275 addNxRegMatch(mb, RegMatch.of(NxmNxReg0.class, Long.valueOf(sepgId)),
276 RegMatch.of(NxmNxReg2.class, Long.valueOf(depgId)));
277 Match match = mb.build();
278 FlowId flowId = FlowIdUtils.newFlowId(TABLE_ID, "intraallow", match);
279 FlowBuilder flow = base().setId(flowId)
282 .setInstructions(instructions(applyActionIns(nxOutputRegAction(NxmNxReg7.class))));
286 private Flow allowFromTunnel(NodeConnectorId tunPort) {
288 MatchBuilder mb = new MatchBuilder().setInPort(tunPort);
289 addNxRegMatch(mb, RegMatch.of(NxmNxReg1.class, Long.valueOf(0xffffff)));
290 Match match = mb.build();
291 FlowId flowId = FlowIdUtils.newFlowId(TABLE_ID, "tunnelallow", match);
292 FlowBuilder flow = base().setId(flowId)
295 .setInstructions(instructions(applyActionIns(nxOutputRegAction(NxmNxReg7.class))));
300 private void syncPolicy(OfWriter ofWriter, NetworkElements netElements, List<RuleGroup> rgs, PolicyPair policyPair) {
301 int priority = 65000;
302 for (RuleGroup rg : rgs) {
303 TenantId tenantId = rg.getContractTenant().getId();
304 IndexedTenant tenant = ctx.getPolicyResolver().getTenant(tenantId);
305 for (Rule r : rg.getRules()) {
306 syncDirection(ofWriter, netElements, tenant, policyPair, r, Direction.In, priority);
307 syncDirection(ofWriter, netElements, tenant, policyPair, r, Direction.Out, priority);
315 * Private internal class for ordering Actions in Rules. The order is
316 * determined first by the value of the order parameter, with the lower
317 * order actions being applied first; for Actions with either the same order
318 * or no order, ordering is lexicographical by name.
320 private static class ActionRefComparator implements Comparator<ActionRef> {
322 public static final ActionRefComparator INSTANCE = new ActionRefComparator();
325 public int compare(ActionRef arg0, ActionRef arg1) {
326 return ComparisonChain.start()
327 .compare(arg0.getOrder(), arg1.getOrder(), Ordering.natural().nullsLast())
328 .compare(arg0.getName().getValue(), arg1.getName().getValue(), Ordering.natural().nullsLast())
334 private void syncDirection(OfWriter ofWriter, NetworkElements netElements, IndexedTenant contractTenant,
335 PolicyPair policyPair, Rule rule, Direction direction, int priority) {
338 Map<String, ParameterValue> paramsFromClassifier = new HashMap<>();
339 Set<ClassifierDefinitionId> classifiers = new HashSet<>();
340 for (ClassifierRef cr : rule.getClassifierRef()) {
341 if (cr.getDirection() != null && !cr.getDirection().equals(Direction.Bidirectional)
342 && !cr.getDirection().equals(direction)) {
346 // XXX - TODO - implement connection tracking (requires openflow
347 // extension and data plane support - in 2.4. Will need to handle
348 // case where we are working with mix of nodes.
350 ClassifierInstance ci = contractTenant.getClassifier(cr.getInstanceName());
352 // XXX TODO fail the match and raise an exception
353 LOG.warn("Classifier instance {} not found", cr.getInstanceName().getValue());
356 Classifier cfier = SubjectFeatures.getClassifier(ci.getClassifierDefinitionId());
358 // XXX TODO fail the match and raise an exception
359 LOG.warn("Classifier definition {} not found", ci.getClassifierDefinitionId().getValue());
362 classifiers.add(new ClassifierDefinitionId(ci.getClassifierDefinitionId()));
363 for (ParameterValue v : ci.getParameterValue()) {
364 if (paramsFromClassifier.get(v.getName().getValue()) == null) {
365 if (v.getIntValue() != null || v.getStringValue() != null || v.getRangeValue() != null) {
366 paramsFromClassifier.put(v.getName().getValue(), v);
369 if (!paramsFromClassifier.get(v.getName().getValue()).equals(v)) {
370 throw new IllegalArgumentException("Classification error in rule: " + rule.getName()
371 + ".\nCause: " + "Classification conflict detected at parameter " + v.getName());
376 if (classifiers.isEmpty()) {
379 List<Map<String, ParameterValue>> derivedParamsByName = ParamDerivator.ETHER_TYPE_DERIVATOR.deriveParameter(paramsFromClassifier);
380 List<MatchBuilder> flowMatchBuilders = new ArrayList<>();
381 for (Map<String, ParameterValue> params : derivedParamsByName) {
382 List<MatchBuilder> matchBuildersToResolve = new ArrayList<>();
383 if (policyPair.consumerEicIpPrefixes.isEmpty() && policyPair.providerEicIpPrefixes.isEmpty()) {
384 matchBuildersToResolve.add(createBaseMatch(direction, policyPair, null, null));
385 } else if (!policyPair.consumerEicIpPrefixes.isEmpty() && policyPair.providerEicIpPrefixes.isEmpty()) {
386 for (IpPrefix sIpPrefix : policyPair.consumerEicIpPrefixes) {
387 matchBuildersToResolve.add(createBaseMatch(direction, policyPair, sIpPrefix, null));
389 } else if (policyPair.consumerEicIpPrefixes.isEmpty() && !policyPair.providerEicIpPrefixes.isEmpty()) {
390 for (IpPrefix dIpPrefix : policyPair.consumerEicIpPrefixes) {
391 matchBuildersToResolve.add(createBaseMatch(direction, policyPair, null, dIpPrefix));
394 for (IpPrefix sIpPrefix : policyPair.consumerEicIpPrefixes) {
395 for (IpPrefix dIpPrefix : policyPair.consumerEicIpPrefixes) {
396 matchBuildersToResolve.add(createBaseMatch(direction, policyPair, sIpPrefix, dIpPrefix));
400 for (ClassifierDefinitionId clDefId : classifiers) {
401 Classifier classifier = SubjectFeatures.getClassifier(clDefId);
402 ClassificationResult result = classifier.updateMatch(matchBuildersToResolve, params);
403 if (!result.isSuccessfull()) {
404 // TODO consider different handling.
405 throw new IllegalArgumentException("Classification conflict detected in rule: " + rule.getName()
406 + ".\nCause: " + result.getErrorMessage());
408 matchBuildersToResolve = new ArrayList<>(result.getMatchBuilders());
410 flowMatchBuilders.addAll(matchBuildersToResolve);
414 * Create the ordered action list. The implicit action is "allow", and
415 * is therefore always in the list
418 List<ActionBuilder> actionBuilderList = new ArrayList<ActionBuilder>();
419 if (rule.getActionRef() != null) {
421 * Pre-sort by references using order, then name
423 List<ActionRef> actionRefList = new ArrayList<ActionRef>(rule.getActionRef());
424 Collections.sort(actionRefList, ActionRefComparator.INSTANCE);
426 for (ActionRef actionRule : actionRefList) {
427 ActionInstance actionInstance = contractTenant.getAction(actionRule.getName());
428 if (actionInstance == null) {
429 // XXX TODO fail the match and raise an exception
430 LOG.warn("Action instance {} not found", actionRule.getName().getValue());
433 Action action = SubjectFeatures.getAction(actionInstance.getActionDefinitionId());
434 if (action == null) {
435 // XXX TODO fail the match and raise an exception
436 LOG.warn("Action definition {} not found", actionInstance.getActionDefinitionId().getValue());
440 Map<String, Object> params = new HashMap<>();
441 if (actionInstance.getParameterValue() != null) {
442 for (ParameterValue v : actionInstance.getParameterValue()) {
443 if (v.getName() == null)
445 if (v.getIntValue() != null) {
446 params.put(v.getName().getValue(), v.getIntValue());
447 } else if (v.getStringValue() != null) {
448 params.put(v.getName().getValue(), v.getStringValue());
453 * Convert the GBP Action to one or more OpenFlow Actions
455 if (!(actionRefList.indexOf(actionRule) == (actionRefList.size() - 1) && action.equals(SubjectFeatures.getAction(AllowActionDefinition.DEFINITION.getId())))) {
456 actionBuilderList = action.updateAction(actionBuilderList, params, actionRule.getOrder(), netElements, policyPair,
457 ofWriter, ctx, direction);
461 FlowBuilder flow = base().setPriority(Integer.valueOf(priority));
462 for (MatchBuilder mb : flowMatchBuilders) {
463 Match match = mb.build();
464 FlowId flowId = FlowIdUtils.newFlowId(TABLE_ID, "cg", match);
465 flow.setMatch(match).setId(flowId).setPriority(Integer.valueOf(priority));
468 * If destination is External, the last Action ALLOW must be changed to goto
469 * NAT/External table.
470 * If actionBuilderList is empty (we removed the last Allow) then go straight to
471 * ExternalMapper table.
474 if (ctx.getEndpointManager().isExternal(netElements.getDstEp())) {
475 flow.setInstructions(instructions(getGotoEgressNatInstruction()));
476 } else if (actionBuilderList == null) {
477 //TODO - analyse, what happen for unknown action, SFC, etc.
478 LOG.warn("Action builder list not found, partially flow which is not created: {}", flow.build());
480 } else if (actionBuilderList.isEmpty()) {
481 flow.setInstructions(instructions(getGotoExternalInstruction()));
483 flow.setInstructions(instructions(applyActionIns(actionBuilderList), getGotoExternalInstruction()));
485 ofWriter.writeFlow(netElements.getLocalNodeId(), TABLE_ID, flow.build());
489 private MatchBuilder createBaseMatch(Direction direction, PolicyPair policyPair, IpPrefix sIpPrefix,
490 IpPrefix dIpPrefix) {
491 MatchBuilder baseMatch = new MatchBuilder();
492 if (direction.equals(Direction.In)) {
493 addNxRegMatch(baseMatch, RegMatch.of(NxmNxReg0.class, Long.valueOf(policyPair.consumerEpgId)),
494 RegMatch.of(NxmNxReg1.class, Long.valueOf(policyPair.consumerCondGrpId)),
495 RegMatch.of(NxmNxReg2.class, Long.valueOf(policyPair.providerEpgId)),
496 RegMatch.of(NxmNxReg3.class, Long.valueOf(policyPair.providerCondGrpId)));
497 if (sIpPrefix != null) {
498 baseMatch.setLayer3Match(createLayer3Match(sIpPrefix, true));
500 if (dIpPrefix != null) {
501 baseMatch.setLayer3Match(createLayer3Match(dIpPrefix, true));
504 addNxRegMatch(baseMatch, RegMatch.of(NxmNxReg0.class, Long.valueOf(policyPair.providerEpgId)),
505 RegMatch.of(NxmNxReg1.class, Long.valueOf(policyPair.providerCondGrpId)),
506 RegMatch.of(NxmNxReg2.class, Long.valueOf(policyPair.consumerEpgId)),
507 RegMatch.of(NxmNxReg3.class, Long.valueOf(policyPair.consumerCondGrpId)));
508 if (sIpPrefix != null) {
509 baseMatch.setLayer3Match(createLayer3Match(sIpPrefix, false));
511 if (dIpPrefix != null) {
512 baseMatch.setLayer3Match(createLayer3Match(dIpPrefix, false));
518 private Layer3Match createLayer3Match(IpPrefix ipPrefix, boolean isSrc) {
519 if (ipPrefix.getIpv4Prefix() != null) {
521 return new Ipv4MatchBuilder().setIpv4Source(ipPrefix.getIpv4Prefix()).build();
523 return new Ipv4MatchBuilder().setIpv4Destination(ipPrefix.getIpv4Prefix()).build();
527 return new Ipv6MatchBuilder().setIpv6Source(ipPrefix.getIpv6Prefix()).build();
529 return new Ipv6MatchBuilder().setIpv6Destination(ipPrefix.getIpv6Prefix()).build();
534 // TODO: move to a common utils for all renderers
535 public List<Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>>> getActiveRulesBetweenEps(Policy policy,
536 Endpoint consEp, Endpoint provEp) {
537 List<Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>>> rulesWithEpConstraints = new ArrayList<>();
538 if (policy.getRuleMap() != null) {
539 for (Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>> cell : policy.getRuleMap().cellSet()) {
540 EndpointConstraint consEpConstraint = cell.getRowKey();
541 EndpointConstraint provEpConstraint = cell.getColumnKey();
542 if (epMatchesConstraint(consEp, consEpConstraint) && epMatchesConstraint(provEp, provEpConstraint)) {
543 rulesWithEpConstraints.add(cell);
547 return rulesWithEpConstraints;
550 private boolean epMatchesConstraint(Endpoint ep, EndpointConstraint constraint) {
551 List<ConditionName> epConditions = Collections.emptyList();
552 if (ep.getCondition() != null) {
553 epConditions = ep.getCondition();
555 return constraint.getConditionSet().matches(epConditions);
558 private static org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction getGotoEgressNatInstruction() {
559 return gotoEgressNatInstruction;
562 private static org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction getGotoExternalInstruction() {
563 return gotoExternalInstruction;
567 public static class PolicyPair {
569 private final int consumerEpgId;
570 private final int providerEpgId;
571 private final int consumerCondGrpId;
572 private final int providerCondGrpId;
573 private final Set<IpPrefix> consumerEicIpPrefixes;
574 private final Set<IpPrefix> providerEicIpPrefixes;
575 private NodeId consumerEpNodeId;
576 private NodeId providerEpNodeId;
578 public int getConsumerEpgId() {
579 return consumerEpgId;
582 public int getProviderEpgId() {
583 return providerEpgId;
586 public NodeId getConsumerEpNodeId() {
587 return consumerEpNodeId;
590 public NodeId getProviderEpNodeId() {
591 return providerEpNodeId;
594 public PolicyPair(int consumerEpgId, int providerEpgId, int consumerCondGrpId, int providerCondGrpId,
595 Set<IpPrefix> consumerEicIpPrefixes, Set<IpPrefix> providerEicIpPrefixes, NodeId consumerEpNodeId, NodeId providerEpNodeId) {
597 this.consumerEpgId = consumerEpgId;
598 this.providerEpgId = providerEpgId;
599 this.consumerCondGrpId = consumerCondGrpId;
600 this.providerCondGrpId = providerCondGrpId;
601 this.consumerEicIpPrefixes = consumerEicIpPrefixes;
602 this.providerEicIpPrefixes = providerEicIpPrefixes;
603 this.consumerEpNodeId = consumerEpNodeId;
604 this.providerEpNodeId = providerEpNodeId;
608 public int hashCode() {
609 final int prime = 31;
611 result = prime * result + ((providerEicIpPrefixes == null) ? 0 : providerEicIpPrefixes.hashCode());
612 result = prime * result + providerCondGrpId;
613 result = prime * result + providerEpgId;
614 result = prime * result + ((consumerEicIpPrefixes == null) ? 0 : consumerEicIpPrefixes.hashCode());
615 result = prime * result + consumerCondGrpId;
616 result = prime * result + consumerEpgId;
617 result = prime * result + ((consumerEpNodeId == null) ? 0 : consumerEpNodeId.hashCode());
618 result = prime * result + ((providerEpNodeId == null) ? 0 : providerEpNodeId.hashCode());
624 public boolean equals(Object obj) {
629 if (getClass() != obj.getClass())
631 PolicyPair other = (PolicyPair) obj;
632 if (providerEicIpPrefixes == null) {
633 if (other.providerEicIpPrefixes != null) {
636 } else if (!providerEicIpPrefixes.equals(other.providerEicIpPrefixes)) {
639 if (consumerEicIpPrefixes == null) {
640 if (other.consumerEicIpPrefixes != null) {
643 } else if (!consumerEicIpPrefixes.equals(other.consumerEicIpPrefixes)) {
646 if (consumerEpNodeId == null) {
647 if (other.consumerEpNodeId != null) {
650 } else if (!consumerEpNodeId.getValue().equals(other.consumerEpNodeId.getValue())) {
653 if (providerEpNodeId == null) {
654 if (other.providerEpNodeId != null) {
657 } else if (!providerEpNodeId.getValue().equals(other.providerEpNodeId.getValue())) {
660 if (providerCondGrpId != other.providerCondGrpId)
662 if (providerEpgId != other.providerEpgId)
664 if (consumerCondGrpId != other.consumerCondGrpId)
666 if (consumerEpgId != other.consumerEpgId)
673 public String toString() {
674 return new StringBuilder().append("consumerEPG: ")
675 .append(consumerEpgId)
676 .append("consumerCG: ")
677 .append(consumerCondGrpId)
678 .append("providerEPG: ")
679 .append(providerEpgId)
680 .append("providerCG: ")
681 .append(providerCondGrpId)
682 .append("consumerEpNodeId: ")
683 .append(consumerEpNodeId)
684 .append("providerEpNodeId: ")
685 .append(providerEpNodeId)
686 .append("consumerEicIpPrefixes: ")
687 .append(consumerEicIpPrefixes)
688 .append("providerEicIpPrefixes: ")
689 .append(providerEicIpPrefixes)
694 public class NetworkElements {
696 private Endpoint srcEp;
697 private Endpoint dstEp;
698 private NodeId srcNodeId;
699 private NodeId dstNodeId;
700 private NodeId localNodeId;
701 private EndpointFwdCtxOrdinals srcEpOrds;
702 private EndpointFwdCtxOrdinals dstEpOrds;
704 public NetworkElements(Endpoint srcEp, Endpoint dstEp, NodeId nodeId, OfContext ctx, PolicyInfo policyInfo)
706 Preconditions.checkArgument(srcEp.getAugmentation(OfOverlayContext.class) != null);
707 Preconditions.checkArgument(dstEp.getAugmentation(OfOverlayContext.class) != null);
711 this.localNodeId = nodeId;
712 this.srcEpOrds = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, policyInfo, srcEp);
713 if (this.srcEpOrds == null) {
714 LOG.debug("getEndpointFwdCtxOrdinals is null for EP {}", srcEp);
717 this.dstEpOrds = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, policyInfo, dstEp);
718 if (this.dstEpOrds == null) {
719 LOG.debug("getEndpointFwdCtxOrdinals is null for EP {}", dstEp);
722 this.dstNodeId = dstEp.getAugmentation(OfOverlayContext.class).getNodeId();
723 this.srcNodeId = srcEp.getAugmentation(OfOverlayContext.class).getNodeId();
727 public Endpoint getSrcEp() {
732 Endpoint getDstEp() {
737 public NodeId getSrcNodeId() {
742 public NodeId getDstNodeId() {
747 public NodeId getLocalNodeId() {
752 public EndpointFwdCtxOrdinals getSrcEpOrds() {
757 public EndpointFwdCtxOrdinals getDstEpOrds() {