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.Collection;
19 import java.util.Collections;
20 import java.util.Comparator;
21 import java.util.HashMap;
22 import java.util.HashSet;
23 import java.util.List;
27 import javax.annotation.concurrent.Immutable;
29 import org.opendaylight.groupbasedpolicy.api.sf.AllowActionDefinition;
30 import org.opendaylight.groupbasedpolicy.api.sf.EtherTypeClassifierDefinition;
31 import org.opendaylight.groupbasedpolicy.api.sf.IpProtoClassifierDefinition;
32 import org.opendaylight.groupbasedpolicy.api.sf.L4ClassifierDefinition;
33 import org.opendaylight.groupbasedpolicy.dto.EgKey;
34 import org.opendaylight.groupbasedpolicy.dto.EndpointConstraint;
35 import org.opendaylight.groupbasedpolicy.dto.EpKey;
36 import org.opendaylight.groupbasedpolicy.dto.IndexedTenant;
37 import org.opendaylight.groupbasedpolicy.dto.Policy;
38 import org.opendaylight.groupbasedpolicy.dto.RuleGroup;
39 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
40 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfWriter;
41 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.endpoint.EndpointManager;
42 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.RegMatch;
43 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OrdinalFactory.EndpointFwdCtxOrdinals;
44 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.Action;
45 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.AllowAction;
46 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.ChainAction;
47 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.ClassificationResult;
48 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.Classifier;
49 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.ParamDerivator;
50 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.SubjectFeatures;
51 import org.opendaylight.groupbasedpolicy.util.TenantUtils;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Key;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.l3endpoint.rev151217.NatAddress;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.action.refs.ActionRef;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRef;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.EndpointGroup;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.EndpointGroup.IntraGroupPolicy;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.ExternalImplicitGroup;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.subject.Rule;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ActionInstance;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ClassifierInstance;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchBuilder;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg0;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg1;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg2;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg3;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg5;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg7;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeVxlan;
91 import org.slf4j.Logger;
92 import org.slf4j.LoggerFactory;
94 import com.google.common.collect.ArrayListMultimap;
95 import com.google.common.collect.ComparisonChain;
96 import com.google.common.collect.ListMultimap;
97 import com.google.common.collect.Ordering;
98 import com.google.common.collect.Table.Cell;
101 * Manage the table that enforces policy on the traffic. Traffic is denied
102 * unless specifically allowed by policy
104 public class PolicyEnforcer extends FlowTable {
106 private static final Logger LOG = LoggerFactory.getLogger(PolicyEnforcer.class);
107 public static short TABLE_ID;
108 private static boolean isReversedPolicy;
109 private static org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction gotoEgressNatInstruction;
110 private static org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction gotoExternalInstruction;
111 private HashSet<PolicyPair> visitedPairs = new HashSet<>();
112 private HashSet<PolicyPair> visitedReversePairs = new HashSet<>();
113 private List<Rule> reversedActiveRules = new ArrayList<>();
114 private ListMultimap<EgKey, EgKey> resolvedEpgPairs = ArrayListMultimap.create();
115 private boolean directPathFlowsCreated = false;
116 private boolean reversePathFlowsCreated = false;
118 public PolicyEnforcer(OfContext ctx, short tableId) {
121 isReversedPolicy = false;
122 gotoEgressNatInstruction = gotoTableIns(ctx.getPolicyManager().getTABLEID_EGRESS_NAT());
123 gotoExternalInstruction = gotoTableIns(ctx.getPolicyManager().getTABLEID_EXTERNAL_MAPPER());
126 private static org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction getGotoEgressNatInstruction() {
127 return gotoEgressNatInstruction;
130 private static org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction getGotoExternalInstruction() {
131 return gotoExternalInstruction;
135 public short getTableId() {
140 public void sync(NodeId nodeId, OfWriter ofWriter) throws Exception {
142 ofWriter.writeFlow(nodeId, TABLE_ID, dropFlow(1, null, TABLE_ID));
144 NodeConnectorId tunPort = ctx.getSwitchManager().getTunnelPort(nodeId, TunnelTypeVxlan.class);
145 if (tunPort != null) {
146 ofWriter.writeFlow(nodeId, TABLE_ID, allowFromTunnel(tunPort));
149 visitedPairs = new HashSet<>();
150 reversedActiveRules = new ArrayList<>();
151 visitedReversePairs = new HashSet<>();
152 resolvedEpgPairs = ArrayListMultimap.create();
154 // Used for ARP flows
155 Set<Integer> fdIds = new HashSet<>();
157 for (Endpoint sourceEp : ctx.getEndpointManager().getEndpointsForNode(nodeId)) {
158 for (EgKey sourceEpgKey : ctx.getEndpointManager().getEgKeysForEndpoint(sourceEp)) {
159 Set<EgKey> peers = ctx.getCurrentPolicy().getPeers(sourceEpgKey);
160 for (EgKey destinationEpgKey : peers) {
162 Set<Endpoint> destinationEndpoints = new HashSet<>();
163 destinationEndpoints.addAll(ctx.getEndpointManager().getEndpointsForGroup(destinationEpgKey));
164 destinationEndpoints.addAll(ctx.getEndpointManager().getExtEpsNoLocForGroup(destinationEpgKey));
165 for (Endpoint destinationEp : destinationEndpoints) {
167 EndpointFwdCtxOrdinals srcEpFwdCxtOrdinals = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, sourceEp);
168 if (srcEpFwdCxtOrdinals == null) {
169 LOG.debug("Method getEndpointFwdCtxOrdinals returned null for EP {}", sourceEp);
173 EndpointFwdCtxOrdinals dstEpFwdCxtOrdinals = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, destinationEp);
174 if (dstEpFwdCxtOrdinals == null) {
175 LOG.debug("Method getEndpointFwdCtxOrdinals returned null for EP {}", destinationEp);
179 fdIds.add(srcEpFwdCxtOrdinals.getFdId());
180 NetworkElements netElements = new NetworkElements(sourceEp, destinationEp, sourceEpgKey,
181 destinationEpgKey, nodeId, ctx);
183 // Get policy in both directions
184 Policy sourceEpgPolicy = ctx.getCurrentPolicy().getPolicy(destinationEpgKey, sourceEpgKey);
185 Policy destinationEpgPolicy = ctx.getCurrentPolicy().getPolicy(sourceEpgKey, destinationEpgKey);
186 reversedActiveRules = getRules(getActiveRulesBetweenEps(destinationEpgPolicy, sourceEp, destinationEp));
188 // Resolve flows in both directions if possible according to policy. Get back status of resolution
189 PathStatus status = resolveSourceEpgPolicy(ofWriter, netElements, sourceEpgPolicy);
191 // When source Epg policy creates no flows, destination Epg policy has to be resolved
192 if (status.equals(PathStatus.none)) {
193 resolveDestinationEpgPolicy(ofWriter, netElements, destinationEpgPolicy, false);
195 // When source Epg policy creates flows only in one direction, the other direction has to be
196 // created here. Is essential to revert directions to prevent flow overriding and incorrect nsp
198 else if (status.equals(PathStatus.partial)) {
199 resolveDestinationEpgPolicy(ofWriter, netElements, destinationEpgPolicy, true);
207 allowSameEpg(nodeId, ofWriter);
209 // Write ARP flows per flood domain
210 for (Integer fdId : fdIds) {
211 ofWriter.writeFlow(nodeId, TABLE_ID, createArpFlow(fdId));
215 private PathStatus resolveSourceEpgPolicy(OfWriter ofWriter, NetworkElements netElements, Policy directPolicy) {
216 isReversedPolicy = false;
217 directPathFlowsCreated = false;
218 reversePathFlowsCreated = false;
220 for (Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>> activeRulesByConstraints : getActiveRulesBetweenEps(
221 directPolicy, netElements.getDstEp(), netElements.getSrcEp())) {
222 Set<IpPrefix> sIpPrefixes = Policy.getIpPrefixesFrom(activeRulesByConstraints.getRowKey()
224 Set<IpPrefix> dIpPrefixes = Policy.getIpPrefixesFrom(activeRulesByConstraints.getColumnKey()
226 PolicyPair policyPair = new PolicyPair(netElements.getDstEpOrdinals().getEpgId(), netElements.getSrcEpOrdinals().getEpgId(),
227 netElements.getDstEpOrdinals().getCgId(), netElements.getSrcEpOrdinals().getCgId(), dIpPrefixes, sIpPrefixes,
228 netElements.getDstNodeId(), netElements.getSrcNodeId());
229 if (visitedPairs.contains(policyPair)) {
230 LOG.trace("PolicyEnforcer: Already visited PolicyPair {}, endpoints {} {} skipped",
231 policyPair, netElements.getSrcEp().getKey(), netElements.getDstEp().getKey());
234 LOG.trace("PolicyEnforcer: Visiting PolicyPair {} endpoints {} {}", policyPair,
235 netElements.getSrcEp().getKey(), netElements.getDstEp().getKey());
236 visitedPairs.add(policyPair);
239 int priority = 65000;
240 for (RuleGroup rg : activeRulesByConstraints.getValue()) {
241 TenantId tenantId = rg.getContractTenant().getId();
242 IndexedTenant tenant = ctx.getTenant(tenantId);
243 for (Rule rule : rg.getRules()) {
245 // Find all rules in the same traffic direction
246 List<Rule> sameDirectionRules = findRulesInSameDirection(rule, reversedActiveRules);
247 if (sameDirectionRules.isEmpty()) {
248 sameDirectionRules.add(rule);
250 sameDirectionRules = Ordering.from(TenantUtils.RULE_COMPARATOR)
251 .immutableSortedCopy(sameDirectionRules);
253 // Create flows for every pair of rules
254 for (Rule oppositeRule : sameDirectionRules) {
256 // Evaluate which rule has more specific matches
257 Rule ruleWithMatches = findRuleWithSpecificMatches(rule, oppositeRule, tenant);
258 Rule ruleWithActions = mergeRuleActions(rule, oppositeRule, tenant);
259 if (ruleWithMatches == null) {
260 LOG.trace("No matches found for pair of rules {}, {}", rule, oppositeRule);
263 if (ruleWithActions == null) {
264 LOG.trace("No actions found for pair of rules {}, {}", rule, oppositeRule);
268 // Preserve original rule direction
269 Set<Direction> directions = getRuleDirections(rule);
271 for(Direction direction : directions) {
273 // Create list of matches/actions. Also creates chain flows when specific action requires it
274 List<MatchBuilder> inMatches = createMatches(Direction.In, policyPair, tenant,
276 List<MatchBuilder> outMatches = createMatches(Direction.Out, policyPair, tenant,
279 List<ActionBuilder> actions = createActions(ofWriter, netElements, direction,
280 policyPair, tenant, ruleWithActions, false);
283 createFlows(inMatches, actions, netElements, ofWriter, priority);
284 createFlows(outMatches, actions, netElements, ofWriter, priority);
288 // Keep info about what direction has flows already created
289 if (direction.equals(Direction.In)) {
290 directPathFlowsCreated = true;
292 if (direction.equals(Direction.Out)) {
293 reversePathFlowsCreated = true;
296 // Fully resolved Ep groups are saved to prevent duplicates
297 if (directPathFlowsCreated && reversePathFlowsCreated) {
298 LOG.trace("Epg pair added: {}, {} ", netElements.getSrcEpg(), netElements.getDstEpg());
299 resolvedEpgPairs.put(netElements.getSrcEpg(), netElements.getDstEpg());
307 // Returns appropriate result of resolving
308 if (directPathFlowsCreated && reversePathFlowsCreated) {
309 return PathStatus.both;
310 } else if ((!directPathFlowsCreated && reversePathFlowsCreated) || (directPathFlowsCreated && !reversePathFlowsCreated)) {
311 return PathStatus.partial;
313 return PathStatus.none;
317 private Set<Direction> getRuleDirections(Rule ruleWithMatches) {
318 Set<Direction> directions = new HashSet<>();
319 for (ClassifierRef classifierRef : ruleWithMatches.getClassifierRef()) {
320 if (!directions.contains(classifierRef.getDirection()) && classifierRef.getDirection() == Direction.In) {
321 directions.add(classifierRef.getDirection());
323 if (!directions.contains(classifierRef.getDirection()) && classifierRef.getDirection() == Direction.Out) {
324 directions.add(classifierRef.getDirection());
327 if (directions.isEmpty()) {
328 directions.add(Direction.Bidirectional);
333 private Rule mergeRuleActions(Rule rule, Rule oppositeRule, IndexedTenant tenant) {
334 if (oppositeRule.equals(rule)) {
338 Action ruleAction = null;
339 Action oppositeRuleAction = null;
341 // For now, only allow action and chain action is supported
342 for (ActionRef actionRef : rule.getActionRef()) {
343 ActionInstance actionInstance = tenant.getAction(actionRef.getName());
344 if (actionRef.getOrder() == 0 && (actionInstance.getActionDefinitionId().equals(new AllowAction().getId()))) {
345 ruleAction = new AllowAction();
347 if (actionRef.getOrder() == 0 && (actionInstance.getActionDefinitionId().equals(new ChainAction().getId()))) {
348 ruleAction = new ChainAction();
351 for (ActionRef actionRef : oppositeRule.getActionRef()) {
352 ActionInstance actionInstance = tenant.getAction(actionRef.getName());
353 if (actionRef.getOrder() == 0 && (actionInstance.getActionDefinitionId().equals(new AllowAction().getId()))) {
354 oppositeRuleAction = new AllowAction();
356 if (actionRef.getOrder() == 0 && (actionInstance.getActionDefinitionId().equals(new ChainAction().getId()))) {
357 oppositeRuleAction = new ChainAction();
361 if (ruleAction == null && oppositeRuleAction == null) {
363 } else if (ruleAction != null && ruleAction.getClass().equals(AllowAction.class)) {
365 } else if (oppositeRuleAction != null && oppositeRuleAction.getClass().equals(AllowAction.class)) {
368 // TODO both rules have chain action - add support for more different chain actions. This works for now
373 private Rule findRuleWithSpecificMatches(Rule rule, Rule oppositeRule, IndexedTenant tenant) {
374 if (oppositeRule.equals(rule)) {
378 // TODO check all classifierRefs
379 ClassifierRef ruleClassifierRef = rule.getClassifierRef().get(0);
380 ClassifierRef oppositeRuleClassifierRef = oppositeRule.getClassifierRef().get(0);
382 ClassifierInstance ruleClassifierInstance = tenant.getClassifier(ruleClassifierRef.getInstanceName());
383 ClassifierInstance oppositeRuleClassifierInstance = tenant.getClassifier(oppositeRuleClassifierRef.getInstanceName());
385 if (ruleClassifierInstance == null) {
386 LOG.trace("Classifier instance not found, ClassifierRef name: {} ", ruleClassifierRef.getInstanceName());
389 if (oppositeRuleClassifierInstance == null) {
390 LOG.trace("Opposite classifier instance not found, ClassifierRef name: {} ", oppositeRuleClassifierRef.getInstanceName());
394 // Check ethertype. Values must be equal
395 for (ParameterValue ruleParameter : ruleClassifierInstance.getParameterValue()) {
396 for (ParameterValue oppositeRuleParameter : oppositeRuleClassifierInstance.getParameterValue()) {
397 if ((ruleParameter.getName().getValue().equals(EtherTypeClassifierDefinition.ETHERTYPE_PARAM))
398 && oppositeRuleParameter.getName().getValue().equals(EtherTypeClassifierDefinition.ETHERTYPE_PARAM)) {
399 if (!ruleParameter.getIntValue().equals(oppositeRuleParameter.getIntValue())) {
400 LOG.trace("Ethertype values are not equal, rule: {}, opposite rule: {} ", rule, oppositeRule);
406 // Check proto if exists. Values must be equal or missing
407 ParameterValue ruleProtoParameter = null;
408 ParameterValue oppositeRuleProtoParameter = null;
409 for (ParameterValue ruleParameter : ruleClassifierInstance.getParameterValue()) {
410 if (ruleParameter.getName().getValue().equals(IpProtoClassifierDefinition.PROTO_PARAM)) {
411 ruleProtoParameter = ruleParameter;
414 for (ParameterValue oppositeRuleParameter : oppositeRuleClassifierInstance.getParameterValue()) {
415 if (oppositeRuleParameter.getName().getValue().equals(IpProtoClassifierDefinition.PROTO_PARAM)) {
416 oppositeRuleProtoParameter = oppositeRuleParameter;
420 if (ruleProtoParameter == null || ruleProtoParameter.getIntValue() == null) {
422 } else if (oppositeRuleProtoParameter == null || oppositeRuleProtoParameter.getIntValue() == null) {
424 } else if (!ruleProtoParameter.getIntValue().equals(oppositeRuleProtoParameter.getIntValue())) {
425 LOG.trace("Proto parameters are not equal, rule parameters: {}, opposite rule parameters {} ",
426 ruleProtoParameter, oppositeRuleProtoParameter);
431 // TODO add support for port ranges
432 ParameterValue ruleL4Src = null;
433 ParameterValue oppositeRuleL4Src = null;
434 ParameterValue ruleL4Dst = null;
435 ParameterValue oppositeRuleL4Dst = null;
437 for (ParameterValue ruleParameter : ruleClassifierInstance.getParameterValue()) {
438 if (ruleParameter.getName().getValue().equals(L4ClassifierDefinition.SRC_PORT_PARAM)) {
439 ruleL4Src = ruleParameter;
441 if (ruleParameter.getName().getValue().equals(L4ClassifierDefinition.DST_PORT_PARAM)) {
442 ruleL4Dst = ruleParameter;
445 for (ParameterValue oppositeRuleParameter : oppositeRuleClassifierInstance.getParameterValue()) {
446 if (oppositeRuleParameter.getName().getValue().equals(L4ClassifierDefinition.SRC_PORT_PARAM)) {
447 oppositeRuleL4Src = oppositeRuleParameter;
449 if (oppositeRuleParameter.getName().getValue().equals(L4ClassifierDefinition.DST_PORT_PARAM)) {
450 oppositeRuleL4Dst = oppositeRuleParameter;
454 if (ruleL4Src == null && ruleL4Dst == null && oppositeRuleL4Src == null && oppositeRuleL4Dst == null) {
459 if (ruleL4Src == null && oppositeRuleL4Src != null) {
462 if (ruleL4Src != null && oppositeRuleL4Src == null) {
465 if (ruleL4Src != null && ruleL4Src.getIntValue() != null && oppositeRuleL4Src.getIntValue() != null
466 && ruleL4Src.equals(oppositeRuleL4Src)) {
469 if (ruleL4Src != null && ruleL4Src.getIntValue() != null && oppositeRuleL4Src.getIntValue() != null
470 && !ruleL4Src.equals(oppositeRuleL4Src)) {
475 if (ruleL4Dst == null && oppositeRuleL4Dst != null) {
478 if (ruleL4Dst != null && oppositeRuleL4Dst == null) {
481 if (ruleL4Dst != null && ruleL4Dst.getIntValue() != null && oppositeRuleL4Dst.getIntValue() != null
482 && ruleL4Dst.equals(oppositeRuleL4Dst)) {
485 if (ruleL4Dst != null && ruleL4Dst.getIntValue() != null && oppositeRuleL4Dst.getIntValue() != null
486 && !ruleL4Dst.equals(oppositeRuleL4Dst)) {
493 private void resolveDestinationEpgPolicy(OfWriter ofWriter, NetworkElements netElements, Policy reversedPolicy,
494 boolean isReverted) {
495 isReversedPolicy = true;
496 for (Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>> activeRulesByConstraints : getActiveRulesBetweenEps(
497 reversedPolicy, netElements.getSrcEp(), netElements.getDstEp())) {
498 Set<IpPrefix> sIpPrefixes = Policy.getIpPrefixesFrom(activeRulesByConstraints.getRowKey()
500 Set<IpPrefix> dIpPrefixes = Policy.getIpPrefixesFrom(activeRulesByConstraints.getColumnKey()
502 PolicyPair policyPair = new PolicyPair(netElements.getSrcEpOrdinals().getEpgId(), netElements.getDstEpOrdinals().getEpgId(),
503 netElements.getSrcEpOrdinals().getCgId(), netElements.getDstEpOrdinals().getCgId(), sIpPrefixes, dIpPrefixes,
504 netElements.getSrcNodeId(), netElements.getDstNodeId());
505 if (visitedReversePairs.contains(policyPair)) {
507 "PolicyEnforcer: Reverse: Already visited PolicyPair {}, endpoints {} {} skipped",
508 policyPair, netElements.getSrcEp().getKey(), netElements.getDstEp().getKey());
511 LOG.trace("PolicyEnforcer: Reverse: Visiting: PolicyPair {} via endpoints {} {}",
512 policyPair, netElements.getSrcEp().getKey(), netElements.getDstEp().getKey());
513 visitedReversePairs.add(policyPair);
516 int priority = 65000;
517 for (RuleGroup rg : activeRulesByConstraints.getValue()) {
518 TenantId tenantId = rg.getContractTenant().getId();
519 IndexedTenant tenant = ctx.getTenant(tenantId);
520 for (Rule rule : rg.getRules()) {
522 Set<Direction> directions = getRuleDirections(rule);
523 if (directions.isEmpty()) {
527 for(Direction direction : directions) {
529 // When specific direction flows exists, do not create them again
530 if (direction.equals(Direction.In) && reversePathFlowsCreated) {
533 if (direction.equals(Direction.Out) && directPathFlowsCreated) {
537 List<MatchBuilder> inMatches = createMatches(Direction.In, policyPair, tenant, rule);
538 List<MatchBuilder> outMatches = createMatches(Direction.Out, policyPair, tenant, rule);
540 // In case chain action is called here, it has to know that this is reversed policy to set tunnel
542 List<ActionBuilder> inActions = createActions(ofWriter, netElements, Direction.In, policyPair, tenant,
544 List<ActionBuilder> outActions = createActions(ofWriter, netElements, Direction.Out, policyPair, tenant,
547 createFlows(inMatches, inActions, netElements, ofWriter, priority);
548 createFlows(outMatches, outActions, netElements, ofWriter, priority);
550 if (direction.equals(Direction.In)) {
551 reversePathFlowsCreated = true;
553 if (direction.equals(Direction.Out)) {
554 directPathFlowsCreated = true;
559 if (directPathFlowsCreated && reversePathFlowsCreated) {
560 resolvedEpgPairs.put(netElements.getSrcEpg(), netElements.getDstEpg());
568 private void allowSameEpg(NodeId nodeId, OfWriter ofWriter) throws Exception {
569 for (Endpoint sourceEp : ctx.getEndpointManager().getEndpointsForNode(nodeId)) {
570 for (EgKey sourceEpgKey : ctx.getEndpointManager().getEgKeysForEndpoint(sourceEp)) {
572 IndexedTenant tenant = ctx.getTenant(sourceEpgKey.getTenantId());
573 if (tenant != null) {
574 EndpointGroup group = tenant.getEndpointGroup(sourceEpgKey.getEgId());
576 LOG.debug("EPG {} does not exit and is used in EP {}", sourceEpgKey, sourceEp.getKey());
579 IntraGroupPolicy igp = group.getIntraGroupPolicy();
581 if (igp == null || igp.equals(IntraGroupPolicy.Allow)) {
582 for (Endpoint dstEp : ctx.getEndpointManager().getEndpointsForGroup(sourceEpgKey)) {
583 EndpointFwdCtxOrdinals srcEpFwdCxtOrdinals =
584 OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, sourceEp);
585 if (srcEpFwdCxtOrdinals == null) {
586 LOG.debug("getEndpointFwdCtxOrdinals is null for EP {}", sourceEp);
590 EndpointFwdCtxOrdinals dstEpFwdCxtOrdinals =
591 OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, dstEp);
592 if (dstEpFwdCxtOrdinals == null) {
593 LOG.debug("getEndpointFwdCtxOrdinals is null for EP {}", dstEp);
597 int destinationEpgId = dstEpFwdCxtOrdinals.getEpgId();
598 int sourceEpgId = srcEpFwdCxtOrdinals.getEpgId();
599 ofWriter.writeFlow(nodeId, TABLE_ID, allowSameEpg(sourceEpgId, destinationEpgId));
600 ofWriter.writeFlow(nodeId, TABLE_ID, allowSameEpg(destinationEpgId, sourceEpgId));
608 // Return list of all rules with opposite direction
609 private List<Rule> findRulesInSameDirection(Rule ruleToResolve, List<Rule> reversedRules) {
610 List<Rule> sameDirectionRules = new ArrayList<>();
611 for (Rule ruleToCompare : reversedRules) {
612 for (ClassifierRef classifierRefToCompare : ruleToCompare.getClassifierRef()) {
613 for (ClassifierRef classifierRefToResolve : ruleToResolve.getClassifierRef()) {
614 if (isDirectionOpposite(classifierRefToCompare.getDirection(), classifierRefToResolve.getDirection())) {
615 sameDirectionRules.add(ruleToCompare);
620 return sameDirectionRules;
623 private boolean isDirectionOpposite(Direction one, Direction two) {
624 return ((one.equals(Direction.In) && two.equals(Direction.Out))
625 || (one.equals(Direction.Out) && two.equals(Direction.In)));
628 private List<Rule> getRules(List<Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>>> activeRules) {
629 List<Rule> rules = new ArrayList<>();
630 for (Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>> activeRule : activeRules) {
631 for (RuleGroup ruleGroup : activeRule.getValue()) {
632 for (Rule rule : ruleGroup.getRules()) {
640 private Flow createArpFlow(Integer fdId) {
642 Long etherType = FlowUtils.ARP;
643 // L2 Classifier so 20,000 for now
644 Integer priority = 20000;
646 MatchBuilder mb = new MatchBuilder().setEthernetMatch(FlowUtils.ethernetMatch(null, null, etherType));
648 addNxRegMatch(mb, RegMatch.of(NxmNxReg5.class, Long.valueOf(fdId)));
650 Match match = mb.build();
651 FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "arp", match);
652 return base().setPriority(priority)
655 .setInstructions(instructions(applyActionIns(nxOutputRegAction(NxmNxReg7.class))))
659 private Flow allowSameEpg(int sourceEpgId, int destinationEpgId) {
661 MatchBuilder mb = new MatchBuilder();
662 addNxRegMatch(mb, RegMatch.of(NxmNxReg0.class, (long) sourceEpgId),
663 RegMatch.of(NxmNxReg2.class, (long) destinationEpgId));
664 Match match = mb.build();
665 FlowId flowId = FlowIdUtils.newFlowId(TABLE_ID, "intraallow", match);
666 FlowBuilder flow = base().setId(flowId)
669 .setInstructions(instructions(applyActionIns(nxOutputRegAction(NxmNxReg7.class))));
673 private Flow allowFromTunnel(NodeConnectorId tunPort) {
675 MatchBuilder mb = new MatchBuilder().setInPort(tunPort);
676 addNxRegMatch(mb, RegMatch.of(NxmNxReg1.class, 0xffffffL));
677 Match match = mb.build();
678 FlowId flowId = FlowIdUtils.newFlowId(TABLE_ID, "tunnelallow", match);
679 FlowBuilder flow = base().setId(flowId)
682 .setInstructions(instructions(applyActionIns(nxOutputRegAction(NxmNxReg7.class))));
687 private List<MatchBuilder> createMatches(Direction direction, PolicyPair policyPair, IndexedTenant contractTenant,
689 Map<String, ParameterValue> paramsFromClassifier = new HashMap<>();
690 Set<ClassifierDefinitionId> classifiers = new HashSet<>();
691 for (ClassifierRef cr : rule.getClassifierRef()) {
693 if (cr.getDirection() != null && !cr.getDirection().equals(Direction.Bidirectional)
694 && !cr.getDirection().equals(direction)) {
698 // XXX - TODO - implement connection tracking (requires openflow
699 // extension and data plane support - in 2.4. Will need to handle
700 // case where we are working with mix of nodes.
702 ClassifierInstance ci = contractTenant.getClassifier(cr.getInstanceName());
704 // XXX TODO fail the match and raise an exception
705 LOG.warn("Classifier instance {} not found", cr.getInstanceName().getValue());
708 Classifier classifier = SubjectFeatures.getClassifier(ci.getClassifierDefinitionId());
709 if (classifier == null) {
710 // XXX TODO fail the match and raise an exception
711 LOG.warn("Classifier definition {} not found", ci.getClassifierDefinitionId().getValue());
714 classifiers.add(new ClassifierDefinitionId(ci.getClassifierDefinitionId()));
715 for (ParameterValue v : ci.getParameterValue()) {
716 if (paramsFromClassifier.get(v.getName().getValue()) == null) {
717 if (v.getIntValue() != null || v.getStringValue() != null || v.getRangeValue() != null) {
718 paramsFromClassifier.put(v.getName().getValue(), v);
721 if (!paramsFromClassifier.get(v.getName().getValue()).equals(v)) {
722 throw new IllegalArgumentException("Classification error in rule: " + rule.getName()
723 + ".\nCause: " + "Classification conflict detected at parameter " + v.getName());
728 if (classifiers.isEmpty()) {
731 List<Map<String, ParameterValue>> derivedParamsByName = ParamDerivator.ETHER_TYPE_DERIVATOR.deriveParameter(paramsFromClassifier);
732 List<MatchBuilder> flowMatchBuilders = new ArrayList<>();
733 for (Map<String, ParameterValue> params : derivedParamsByName) {
734 List<MatchBuilder> matchBuildersToResolve = new ArrayList<>();
735 if (policyPair.consumerEicIpPrefixes.isEmpty() && policyPair.providerEicIpPrefixes.isEmpty()) {
736 matchBuildersToResolve.add(createBaseMatch(direction, policyPair, null, null));
737 } else if (!policyPair.consumerEicIpPrefixes.isEmpty() && policyPair.providerEicIpPrefixes.isEmpty()) {
738 for (IpPrefix sIpPrefix : policyPair.consumerEicIpPrefixes) {
739 matchBuildersToResolve.add(createBaseMatch(direction, policyPair, sIpPrefix, null));
741 } else if (policyPair.consumerEicIpPrefixes.isEmpty() && !policyPair.providerEicIpPrefixes.isEmpty()) {
742 for (IpPrefix dIpPrefix : policyPair.consumerEicIpPrefixes) {
743 matchBuildersToResolve.add(createBaseMatch(direction, policyPair, null, dIpPrefix));
746 for (IpPrefix sIpPrefix : policyPair.consumerEicIpPrefixes) {
747 for (IpPrefix dIpPrefix : policyPair.consumerEicIpPrefixes) {
748 matchBuildersToResolve.add(createBaseMatch(direction, policyPair, sIpPrefix, dIpPrefix));
752 for (ClassifierDefinitionId clDefId : classifiers) {
753 Classifier classifier = SubjectFeatures.getClassifier(clDefId);
754 ClassificationResult result = classifier.updateMatch(matchBuildersToResolve, params);
755 if (!result.isSuccessfull()) {
756 // TODO consider different handling.
757 throw new IllegalArgumentException("Classification conflict detected in rule: " + rule.getName()
758 + ".\nCause: " + result.getErrorMessage());
760 matchBuildersToResolve = new ArrayList<>(result.getMatchBuilders());
762 flowMatchBuilders.addAll(matchBuildersToResolve);
764 return flowMatchBuilders;
767 private List<ActionBuilder> createActions(OfWriter ofWriter, NetworkElements netElements, Direction direction, PolicyPair policyPair,
768 IndexedTenant contractTenant, Rule rule, boolean isReversedDirection) {
769 List<ActionBuilder> actionBuilderList = new ArrayList<>();
770 if (rule.getActionRef() != null) {
772 // Pre-sort by references using order, then name
773 List<ActionRef> actionRefList = new ArrayList<>(rule.getActionRef());
774 Collections.sort(actionRefList, ActionRefComparator.INSTANCE);
776 for (ActionRef actionRule : actionRefList) {
777 ActionInstance actionInstance = contractTenant.getAction(actionRule.getName());
778 if (actionInstance == null) {
779 // XXX TODO fail the match and raise an exception
780 LOG.warn("Action instance {} not found", actionRule.getName().getValue());
783 Action action = SubjectFeatures.getAction(actionInstance.getActionDefinitionId());
784 if (action == null) {
785 // XXX TODO fail the match and raise an exception
786 LOG.warn("Action definition {} not found", actionInstance.getActionDefinitionId().getValue());
790 Map<String, Object> params = new HashMap<>();
791 if (actionInstance.getParameterValue() != null) {
792 for (ParameterValue v : actionInstance.getParameterValue()) {
793 if (v.getName() == null)
795 if (v.getIntValue() != null) {
796 params.put(v.getName().getValue(), v.getIntValue());
797 } else if (v.getStringValue() != null) {
798 params.put(v.getName().getValue(), v.getStringValue());
802 if (isReversedDirection) {
803 direction = reverse(direction);
806 // Convert the GBP Action to one or more OpenFlow Actions
807 if (!(actionRefList.indexOf(actionRule) == (actionRefList.size() - 1)
808 && action.equals(SubjectFeatures.getAction(AllowActionDefinition.DEFINITION.getId())))) {
809 actionBuilderList = action.updateAction(actionBuilderList, params, actionRule.getOrder(), netElements,
810 policyPair, ofWriter, ctx, direction);
815 return actionBuilderList;
818 private Direction reverse(Direction direction) {
819 if (direction.equals(Direction.In)) {
820 return Direction.Out;
822 else if(direction.equals(Direction.Out)) {
826 return Direction.Bidirectional;
830 private void createFlows(List<MatchBuilder> flowMatchBuilders, List<ActionBuilder> actionBuilderList, NetworkElements netElements,
831 OfWriter ofWriter, int priority) {
832 FlowBuilder flow = base().setPriority(priority);
833 if(flowMatchBuilders == null) {
836 for (MatchBuilder mb : flowMatchBuilders) {
837 Match match = mb.build();
838 FlowId flowId = FlowIdUtils.newFlowId(TABLE_ID, "cg", match);
839 flow.setMatch(match).setId(flowId).setPriority(priority);
841 // If destination is External, the last Action ALLOW must be changed to goto
842 // NAT/External table.
843 // If actionBuilderList is empty (we removed the last Allow) then go straight to
844 // ExternalMapper table.
846 List<ExternalImplicitGroup> eigs = ctx.getTenant(netElements.getDstEp().getTenant())
849 .getExternalImplicitGroup();
850 boolean performNat = false;
851 for (EndpointL3 natEp : ctx.getEndpointManager().getL3EndpointsWithNat()) {
852 if (natEp.getMacAddress() != null &&
853 natEp.getL2Context() != null &&
854 netElements.getSrcEp().getKey().equals(new EndpointKey(natEp.getL2Context(),
855 natEp.getMacAddress())) &&
856 EndpointManager.isExternal(netElements.getDstEp(), eigs)) {
861 if (actionBuilderList == null) {
862 //TODO - analyse, what happen for unknown action, SFC, etc.
863 LOG.warn("Action builder list not found, partially flow which is not created: {}", flow.build());
866 if (actionBuilderList.isEmpty()) {
867 flow.setInstructions((performNat == true) ? instructions(gotoEgressNatInstruction) : instructions(gotoExternalInstruction));
869 flow.setInstructions(instructions(applyActionIns(actionBuilderList),
870 (performNat == true) ? gotoEgressNatInstruction : gotoExternalInstruction));
872 ofWriter.writeFlow(netElements.getLocalNodeId(), TABLE_ID, flow.build());
876 private MatchBuilder createBaseMatch(Direction direction, PolicyPair policyPair, IpPrefix sIpPrefix,
877 IpPrefix dIpPrefix) {
878 MatchBuilder baseMatch = new MatchBuilder();
879 if (direction.equals(Direction.In)) {
880 addNxRegMatch(baseMatch, RegMatch.of(NxmNxReg0.class, (long) policyPair.consumerEpgId),
881 RegMatch.of(NxmNxReg1.class, (long) policyPair.consumerCondGrpId),
882 RegMatch.of(NxmNxReg2.class, (long) policyPair.providerEpgId),
883 RegMatch.of(NxmNxReg3.class, (long) policyPair.providerCondGrpId));
884 if (sIpPrefix != null) {
885 baseMatch.setLayer3Match(createLayer3Match(sIpPrefix, true));
887 if (dIpPrefix != null) {
888 baseMatch.setLayer3Match(createLayer3Match(dIpPrefix, true));
891 addNxRegMatch(baseMatch, RegMatch.of(NxmNxReg0.class, (long) policyPair.providerEpgId),
892 RegMatch.of(NxmNxReg1.class, (long) policyPair.providerCondGrpId),
893 RegMatch.of(NxmNxReg2.class, (long) policyPair.consumerEpgId),
894 RegMatch.of(NxmNxReg3.class, (long) policyPair.consumerCondGrpId));
895 if (sIpPrefix != null) {
896 baseMatch.setLayer3Match(createLayer3Match(sIpPrefix, false));
898 if (dIpPrefix != null) {
899 baseMatch.setLayer3Match(createLayer3Match(dIpPrefix, false));
905 private Layer3Match createLayer3Match(IpPrefix ipPrefix, boolean isSrc) {
906 if (ipPrefix.getIpv4Prefix() != null) {
908 return new Ipv4MatchBuilder().setIpv4Source(ipPrefix.getIpv4Prefix()).build();
910 return new Ipv4MatchBuilder().setIpv4Destination(ipPrefix.getIpv4Prefix()).build();
914 return new Ipv6MatchBuilder().setIpv6Source(ipPrefix.getIpv6Prefix()).build();
916 return new Ipv6MatchBuilder().setIpv6Destination(ipPrefix.getIpv6Prefix()).build();
921 // TODO: move to a common utils for all renderers
922 private List<Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>>> getActiveRulesBetweenEps(Policy policy,
923 Endpoint consEp, Endpoint provEp) {
924 List<Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>>> rulesWithEpConstraints = new ArrayList<>();
925 for (Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>> cell : policy.getRuleMap().cellSet()) {
926 EndpointConstraint consEpConstraint = cell.getRowKey();
927 EndpointConstraint provEpConstraint = cell.getColumnKey();
928 if (epMatchesConstraint(consEp, consEpConstraint) && epMatchesConstraint(provEp, provEpConstraint)) {
929 rulesWithEpConstraints.add(cell);
932 return rulesWithEpConstraints;
935 private boolean epMatchesConstraint(Endpoint ep, EndpointConstraint constraint) {
936 List<ConditionName> epConditions = Collections.emptyList();
937 if (ep.getCondition() != null) {
938 epConditions = ep.getCondition();
940 return constraint.getConditionSet().matches(epConditions);
943 private enum PathStatus { both, partial, none }
945 public static boolean checkPolicyOrientation() {
946 return isReversedPolicy;
950 * Private internal class for ordering Actions in Rules. The order is
951 * determined first by the value of the order parameter, with the lower
952 * order actions being applied first; for Actions with either the same order
953 * or no order, ordering is lexicographical by name.
955 private static class ActionRefComparator implements Comparator<ActionRef> {
957 public static final ActionRefComparator INSTANCE = new ActionRefComparator();
960 public int compare(ActionRef arg0, ActionRef arg1) {
961 return ComparisonChain.start()
962 .compare(arg0.getOrder(), arg1.getOrder(), Ordering.natural().nullsLast())
963 .compare(arg0.getName().getValue(), arg1.getName().getValue(), Ordering.natural().nullsLast())
970 public static class PolicyPair {
972 private final int consumerEpgId;
973 private final int providerEpgId;
974 private final int consumerCondGrpId;
975 private final int providerCondGrpId;
976 private final Set<IpPrefix> consumerEicIpPrefixes;
977 private final Set<IpPrefix> providerEicIpPrefixes;
978 private final NodeId consumerEpNodeId;
979 private final NodeId providerEpNodeId;
981 public PolicyPair(int consumerEpgId, int providerEpgId, int consumerCondGrpId, int providerCondGrpId,
982 Set<IpPrefix> consumerEicIpPrefixes, Set<IpPrefix> providerEicIpPrefixes, NodeId consumerEpNodeId, NodeId providerEpNodeId) {
984 this.consumerEpgId = consumerEpgId;
985 this.providerEpgId = providerEpgId;
986 this.consumerCondGrpId = consumerCondGrpId;
987 this.providerCondGrpId = providerCondGrpId;
988 this.consumerEicIpPrefixes = consumerEicIpPrefixes;
989 this.providerEicIpPrefixes = providerEicIpPrefixes;
990 this.consumerEpNodeId = consumerEpNodeId;
991 this.providerEpNodeId = providerEpNodeId;
994 public int getConsumerEpgId() {
995 return consumerEpgId;
998 public int getProviderEpgId() {
999 return providerEpgId;
1002 public NodeId getConsumerEpNodeId() {
1003 return consumerEpNodeId;
1006 public NodeId getProviderEpNodeId() {
1007 return providerEpNodeId;
1011 public int hashCode() {
1012 final int prime = 31;
1014 result = prime * result + ((providerEicIpPrefixes == null) ? 0 : providerEicIpPrefixes.hashCode());
1015 result = prime * result + providerCondGrpId;
1016 result = prime * result + providerEpgId;
1017 result = prime * result + ((consumerEicIpPrefixes == null) ? 0 : consumerEicIpPrefixes.hashCode());
1018 result = prime * result + consumerCondGrpId;
1019 result = prime * result + consumerEpgId;
1020 result = prime * result + ((consumerEpNodeId == null) ? 0 : consumerEpNodeId.hashCode());
1021 result = prime * result + ((providerEpNodeId == null) ? 0 : providerEpNodeId.hashCode());
1027 public boolean equals(Object obj) {
1032 if (getClass() != obj.getClass())
1034 PolicyPair other = (PolicyPair) obj;
1035 if (providerEicIpPrefixes == null) {
1036 if (other.providerEicIpPrefixes != null) {
1039 } else if (!providerEicIpPrefixes.equals(other.providerEicIpPrefixes)) {
1042 if (consumerEicIpPrefixes == null) {
1043 if (other.consumerEicIpPrefixes != null) {
1046 } else if (!consumerEicIpPrefixes.equals(other.consumerEicIpPrefixes)) {
1049 if (consumerEpNodeId == null) {
1050 if (other.consumerEpNodeId != null) {
1053 } else if (!consumerEpNodeId.getValue().equals(other.consumerEpNodeId.getValue())) {
1056 if (providerEpNodeId == null) {
1057 if (other.providerEpNodeId != null) {
1060 } else if (!providerEpNodeId.getValue().equals(other.providerEpNodeId.getValue())) {
1063 return (providerCondGrpId == other.providerCondGrpId)
1064 && (providerEpgId == other.providerEpgId)
1065 && (consumerCondGrpId == other.consumerCondGrpId)
1066 && (consumerEpgId == other.consumerEpgId);
1071 public String toString() {
1072 return "consumerEPG: " + consumerEpgId +
1073 "consumerCG: " + consumerCondGrpId +
1074 "providerEPG: " + providerEpgId +
1075 "providerCG: " + providerCondGrpId +
1076 "consumerEpNodeId: " + consumerEpNodeId +
1077 "providerEpNodeId: " + providerEpNodeId +
1078 "consumerEicIpPrefixes: " + consumerEicIpPrefixes +
1079 "providerEicIpPrefixes: " + providerEicIpPrefixes;
1083 public class NetworkElements {
1085 private final Endpoint srcEp;
1086 private final Endpoint dstEp;
1087 private final EgKey srcEpg;
1088 private final EgKey dstEpg;
1089 private NodeId srcNodeId;
1090 private NodeId dstNodeId;
1091 private final NodeId localNodeId;
1092 private EndpointFwdCtxOrdinals srcEpOrdinals;
1093 private EndpointFwdCtxOrdinals dstEpOrdinals;
1095 public NetworkElements(Endpoint srcEp, Endpoint dstEp, EgKey srcEpg, EgKey dstEpg, NodeId nodeId, OfContext ctx) throws Exception {
1098 this.srcEpg = srcEpg;
1099 this.dstEpg = dstEpg;
1100 this.localNodeId = nodeId;
1101 this.srcEpOrdinals = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, srcEp);
1102 if (this.srcEpOrdinals == null) {
1103 LOG.debug("getEndpointFwdCtxOrdinals is null for EP {}", srcEp);
1106 this.dstEpOrdinals = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, dstEp);
1107 if (this.dstEpOrdinals == null) {
1108 LOG.debug("getEndpointFwdCtxOrdinals is null for EP {}", dstEp);
1111 if (dstEp.getAugmentation(OfOverlayContext.class) != null) {
1112 this.dstNodeId = dstEp.getAugmentation(OfOverlayContext.class).getNodeId();
1114 if (srcEp.getAugmentation(OfOverlayContext.class) != null) {
1115 this.srcNodeId = srcEp.getAugmentation(OfOverlayContext.class).getNodeId();
1120 public Endpoint getSrcEp() {
1125 public Endpoint getDstEp() {
1129 public EgKey getSrcEpg() {
1133 public EgKey getDstEpg() {
1137 public NodeId getSrcNodeId() {
1142 public NodeId getDstNodeId() {
1147 public NodeId getLocalNodeId() {
1152 public EndpointFwdCtxOrdinals getSrcEpOrdinals() {
1153 return srcEpOrdinals;
1157 public EndpointFwdCtxOrdinals getDstEpOrdinals() {
1158 return dstEpOrdinals;