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.flow.types.rev131026.instruction.instruction.go.to.table._case.GoToTable;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Key;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.l3endpoint.rev151217.NatAddress;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.action.refs.ActionRef;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRef;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.EndpointGroup;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.EndpointGroup.IntraGroupPolicy;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.ExternalImplicitGroup;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.subject.Rule;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ActionInstance;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ClassifierInstance;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchBuilder;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg0;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg1;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg2;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg3;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg5;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg7;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeVxlan;
92 import org.slf4j.Logger;
93 import org.slf4j.LoggerFactory;
95 import com.google.common.collect.ArrayListMultimap;
96 import com.google.common.collect.ComparisonChain;
97 import com.google.common.collect.ListMultimap;
98 import com.google.common.collect.Ordering;
99 import com.google.common.collect.Table.Cell;
102 * <h1>Manage the table that enforces policy on the traffic. Traffic is denied
103 * unless specifically allowed by policy (table=4)</h1>
105 * In policy enforcer, according to current {@link Policy} specific traffic is sent to SFC (nsp and nsi is set), or from SFC
106 * to some {@link Endpoint} or to another classifier.
108 * <i>Tunnel/overlay flows</i><br>
109 * Priority = 65000 (if more flows, decrements)<br>
111 * - ethertype (tcp, tcp6, ipv6, icmp or missing)<br>
112 * - Reg0 {@link NxmNxReg0}<br>
113 * - Reg1 {@link NxmNxReg1}<br>
114 * - Reg2 {@link NxmNxReg2}<br>
115 * - Reg3 {@link NxmNxReg3}<br>
116 * - L3 for src_ip_prefix (if exists)<br>
117 * - L3 for dst_ip_prefix (if exists)<br>
119 * - set nsi (only chain action)<br>
120 * - set nsp (only chain action)<br>
121 * - {@link GoToTable} EXTERNAL MAPPER table<br>
123 * <i>Allow from tunnel flow</i><br>
124 * Priority = 65000<br>
126 * - Reg1 (set to 0xffffff) {@link NxmNxReg1}<br>
127 * - in_port (should be tunnel port) {@link NodeConnectorId}<br>
129 * - output:port (Reg7) {@link NxmNxReg7}<br>
131 * Traffic is sent from one {@link EndpointGroup} to the same EPG
133 * <i>Allow from same EPG flow</i><br>
134 * Priority = 65000<br>
136 * - Reg0 {@link NxmNxReg0}<br>
137 * - Reg2 {@link NxmNxReg2}<br>
139 * - output:port (Reg7) {@link NxmNxReg7}
141 * <i>Arp flow</i><br>
142 * Priority = 20000<br>
144 * - ethernet match (arp)<br>
145 * - Reg5 {@link NxmNxReg5}<br>
147 * - output:port (Reg7) {@link NxmNxReg7}
150 public class PolicyEnforcer extends FlowTable {
152 private static final Logger LOG = LoggerFactory.getLogger(PolicyEnforcer.class);
153 public static short TABLE_ID;
154 private static boolean isReversedPolicy;
155 private static org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction gotoEgressNatInstruction;
156 private static org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction gotoExternalInstruction;
157 private HashSet<PolicyPair> visitedPairs = new HashSet<>();
158 private HashSet<PolicyPair> visitedReversePairs = new HashSet<>();
159 private List<Rule> reversedActiveRules = new ArrayList<>();
160 private ListMultimap<EgKey, EgKey> resolvedEpgPairs = ArrayListMultimap.create();
161 private boolean directPathFlowsCreated = false;
162 private boolean reversePathFlowsCreated = false;
164 public PolicyEnforcer(OfContext ctx, short tableId) {
167 isReversedPolicy = false;
168 gotoEgressNatInstruction = gotoTableIns(ctx.getPolicyManager().getTABLEID_EGRESS_NAT());
169 gotoExternalInstruction = gotoTableIns(ctx.getPolicyManager().getTABLEID_EXTERNAL_MAPPER());
172 private static org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction getGotoEgressNatInstruction() {
173 return gotoEgressNatInstruction;
176 private static org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction getGotoExternalInstruction() {
177 return gotoExternalInstruction;
181 public short getTableId() {
186 public void sync(NodeId nodeId, OfWriter ofWriter) throws Exception {
188 ofWriter.writeFlow(nodeId, TABLE_ID, dropFlow(1, null, TABLE_ID));
190 NodeConnectorId tunPort = ctx.getSwitchManager().getTunnelPort(nodeId, TunnelTypeVxlan.class);
191 if (tunPort != null) {
192 ofWriter.writeFlow(nodeId, TABLE_ID, allowFromTunnel(tunPort));
195 visitedPairs = new HashSet<>();
196 reversedActiveRules = new ArrayList<>();
197 visitedReversePairs = new HashSet<>();
198 resolvedEpgPairs = ArrayListMultimap.create();
200 // Used for ARP flows
201 Set<Integer> fdIds = new HashSet<>();
203 for (Endpoint sourceEp : ctx.getEndpointManager().getEndpointsForNode(nodeId)) {
204 for (EgKey sourceEpgKey : ctx.getEndpointManager().getEgKeysForEndpoint(sourceEp)) {
205 Set<EgKey> peers = ctx.getCurrentPolicy().getPeers(sourceEpgKey);
206 for (EgKey destinationEpgKey : peers) {
208 Set<Endpoint> destinationEndpoints = new HashSet<>();
209 destinationEndpoints.addAll(ctx.getEndpointManager().getEndpointsForGroup(destinationEpgKey));
210 destinationEndpoints.addAll(ctx.getEndpointManager().getExtEpsNoLocForGroup(destinationEpgKey));
211 for (Endpoint destinationEp : destinationEndpoints) {
213 EndpointFwdCtxOrdinals srcEpFwdCxtOrdinals = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, sourceEp);
214 if (srcEpFwdCxtOrdinals == null) {
215 LOG.debug("Method getEndpointFwdCtxOrdinals returned null for EP {}", sourceEp);
219 EndpointFwdCtxOrdinals dstEpFwdCxtOrdinals = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, destinationEp);
220 if (dstEpFwdCxtOrdinals == null) {
221 LOG.debug("Method getEndpointFwdCtxOrdinals returned null for EP {}", destinationEp);
225 fdIds.add(srcEpFwdCxtOrdinals.getFdId());
226 NetworkElements netElements = new NetworkElements(sourceEp, destinationEp, sourceEpgKey,
227 destinationEpgKey, nodeId, ctx);
229 // Get policy in both directions
230 Policy sourceEpgPolicy = ctx.getCurrentPolicy().getPolicy(destinationEpgKey, sourceEpgKey);
231 Policy destinationEpgPolicy = ctx.getCurrentPolicy().getPolicy(sourceEpgKey, destinationEpgKey);
232 reversedActiveRules = getRules(getActiveRulesBetweenEps(destinationEpgPolicy, sourceEp, destinationEp));
234 // Resolve flows in both directions if possible according to policy. Get back status of resolution
235 PathStatus status = resolveSourceEpgPolicy(ofWriter, netElements, sourceEpgPolicy);
237 // When source Epg policy creates no flows, destination Epg policy has to be resolved
238 if (status.equals(PathStatus.none)) {
239 resolveDestinationEpgPolicy(ofWriter, netElements, destinationEpgPolicy, false);
241 // When source Epg policy creates flows only in one direction, the other direction has to be
242 // created here. Is essential to revert directions to prevent flow overriding and incorrect nsp
244 else if (status.equals(PathStatus.partial)) {
245 resolveDestinationEpgPolicy(ofWriter, netElements, destinationEpgPolicy, true);
253 allowSameEpg(nodeId, ofWriter);
255 // Write ARP flows per flood domain
256 for (Integer fdId : fdIds) {
257 ofWriter.writeFlow(nodeId, TABLE_ID, createArpFlow(fdId));
261 private PathStatus resolveSourceEpgPolicy(OfWriter ofWriter, NetworkElements netElements, Policy directPolicy) {
262 isReversedPolicy = false;
263 directPathFlowsCreated = false;
264 reversePathFlowsCreated = false;
266 for (Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>> activeRulesByConstraints : getActiveRulesBetweenEps(
267 directPolicy, netElements.getDstEp(), netElements.getSrcEp())) {
268 Set<IpPrefix> sIpPrefixes = Policy.getIpPrefixesFrom(activeRulesByConstraints.getRowKey()
270 Set<IpPrefix> dIpPrefixes = Policy.getIpPrefixesFrom(activeRulesByConstraints.getColumnKey()
272 PolicyPair policyPair = new PolicyPair(netElements.getDstEpOrdinals().getEpgId(), netElements.getSrcEpOrdinals().getEpgId(),
273 netElements.getDstEpOrdinals().getCgId(), netElements.getSrcEpOrdinals().getCgId(), dIpPrefixes, sIpPrefixes,
274 netElements.getDstNodeId(), netElements.getSrcNodeId());
275 if (visitedPairs.contains(policyPair)) {
276 LOG.trace("PolicyEnforcer: Already visited PolicyPair {}, endpoints {} {} skipped",
277 policyPair, netElements.getSrcEp().getKey(), netElements.getDstEp().getKey());
280 LOG.trace("PolicyEnforcer: Visiting PolicyPair {} endpoints {} {}", policyPair,
281 netElements.getSrcEp().getKey(), netElements.getDstEp().getKey());
282 visitedPairs.add(policyPair);
285 int priority = 65000;
286 for (RuleGroup rg : activeRulesByConstraints.getValue()) {
287 TenantId tenantId = rg.getContractTenant().getId();
288 IndexedTenant tenant = ctx.getTenant(tenantId);
289 for (Rule rule : rg.getRules()) {
291 // Find all rules in the same traffic direction
292 List<Rule> sameDirectionRules = findRulesInSameDirection(rule, reversedActiveRules);
293 if (sameDirectionRules.isEmpty()) {
294 sameDirectionRules.add(rule);
296 sameDirectionRules = Ordering.from(TenantUtils.RULE_COMPARATOR)
297 .immutableSortedCopy(sameDirectionRules);
299 // Create flows for every pair of rules
300 for (Rule oppositeRule : sameDirectionRules) {
302 // Evaluate which rule has more specific matches
303 Rule ruleWithMatches = findRuleWithSpecificMatches(rule, oppositeRule, tenant);
304 Rule ruleWithActions = mergeRuleActions(rule, oppositeRule, tenant);
305 if (ruleWithMatches == null) {
306 LOG.trace("No matches found for pair of rules {}, {}", rule, oppositeRule);
309 if (ruleWithActions == null) {
310 LOG.trace("No actions found for pair of rules {}, {}", rule, oppositeRule);
314 // Preserve original rule direction
315 Set<Direction> directions = getRuleDirections(rule);
317 for(Direction direction : directions) {
319 // Create list of matches/actions. Also creates chain flows when specific action requires it
320 List<MatchBuilder> inMatches = createMatches(Direction.In, policyPair, tenant,
322 List<MatchBuilder> outMatches = createMatches(Direction.Out, policyPair, tenant,
325 List<ActionBuilder> actions = createActions(ofWriter, netElements, direction,
326 policyPair, tenant, ruleWithActions, false);
329 createFlows(inMatches, actions, netElements, ofWriter, priority);
330 createFlows(outMatches, actions, netElements, ofWriter, priority);
334 // Keep info about what direction has flows already created
335 if (direction.equals(Direction.In)) {
336 directPathFlowsCreated = true;
338 if (direction.equals(Direction.Out)) {
339 reversePathFlowsCreated = true;
342 // Fully resolved Ep groups are saved to prevent duplicates
343 if (directPathFlowsCreated && reversePathFlowsCreated) {
344 LOG.trace("Epg pair added: {}, {} ", netElements.getSrcEpg(), netElements.getDstEpg());
345 resolvedEpgPairs.put(netElements.getSrcEpg(), netElements.getDstEpg());
353 // Returns appropriate result of resolving
354 if (directPathFlowsCreated && reversePathFlowsCreated) {
355 return PathStatus.both;
356 } else if ((!directPathFlowsCreated && reversePathFlowsCreated) || (directPathFlowsCreated && !reversePathFlowsCreated)) {
357 return PathStatus.partial;
359 return PathStatus.none;
363 private Set<Direction> getRuleDirections(Rule ruleWithMatches) {
364 Set<Direction> directions = new HashSet<>();
365 for (ClassifierRef classifierRef : ruleWithMatches.getClassifierRef()) {
366 if (!directions.contains(classifierRef.getDirection()) && classifierRef.getDirection() == Direction.In) {
367 directions.add(classifierRef.getDirection());
369 if (!directions.contains(classifierRef.getDirection()) && classifierRef.getDirection() == Direction.Out) {
370 directions.add(classifierRef.getDirection());
373 if (directions.isEmpty()) {
374 directions.add(Direction.Bidirectional);
379 private Rule mergeRuleActions(Rule rule, Rule oppositeRule, IndexedTenant tenant) {
380 if (oppositeRule.equals(rule)) {
384 Action ruleAction = null;
385 Action oppositeRuleAction = null;
387 // For now, only allow action and chain action is supported
388 for (ActionRef actionRef : rule.getActionRef()) {
389 ActionInstance actionInstance = tenant.getAction(actionRef.getName());
390 if (actionRef.getOrder() == 0 && (actionInstance.getActionDefinitionId().equals(new AllowAction().getId()))) {
391 ruleAction = new AllowAction();
393 if (actionRef.getOrder() == 0 && (actionInstance.getActionDefinitionId().equals(new ChainAction().getId()))) {
394 ruleAction = new ChainAction();
397 for (ActionRef actionRef : oppositeRule.getActionRef()) {
398 ActionInstance actionInstance = tenant.getAction(actionRef.getName());
399 if (actionRef.getOrder() == 0 && (actionInstance.getActionDefinitionId().equals(new AllowAction().getId()))) {
400 oppositeRuleAction = new AllowAction();
402 if (actionRef.getOrder() == 0 && (actionInstance.getActionDefinitionId().equals(new ChainAction().getId()))) {
403 oppositeRuleAction = new ChainAction();
407 if (ruleAction == null && oppositeRuleAction == null) {
409 } else if (ruleAction != null && ruleAction.getClass().equals(AllowAction.class)) {
411 } else if (oppositeRuleAction != null && oppositeRuleAction.getClass().equals(AllowAction.class)) {
414 // TODO both rules have chain action - add support for more different chain actions. This works for now
419 private Rule findRuleWithSpecificMatches(Rule rule, Rule oppositeRule, IndexedTenant tenant) {
420 if (oppositeRule.equals(rule)) {
424 // TODO check all classifierRefs
425 ClassifierRef ruleClassifierRef = rule.getClassifierRef().get(0);
426 ClassifierRef oppositeRuleClassifierRef = oppositeRule.getClassifierRef().get(0);
428 ClassifierInstance ruleClassifierInstance = tenant.getClassifier(ruleClassifierRef.getInstanceName());
429 ClassifierInstance oppositeRuleClassifierInstance = tenant.getClassifier(oppositeRuleClassifierRef.getInstanceName());
431 if (ruleClassifierInstance == null) {
432 LOG.trace("Classifier instance not found, ClassifierRef name: {} ", ruleClassifierRef.getInstanceName());
435 if (oppositeRuleClassifierInstance == null) {
436 LOG.trace("Opposite classifier instance not found, ClassifierRef name: {} ", oppositeRuleClassifierRef.getInstanceName());
440 // Check ethertype. Values must be equal
441 for (ParameterValue ruleParameter : ruleClassifierInstance.getParameterValue()) {
442 for (ParameterValue oppositeRuleParameter : oppositeRuleClassifierInstance.getParameterValue()) {
443 if ((ruleParameter.getName().getValue().equals(EtherTypeClassifierDefinition.ETHERTYPE_PARAM))
444 && oppositeRuleParameter.getName().getValue().equals(EtherTypeClassifierDefinition.ETHERTYPE_PARAM)) {
445 if (!ruleParameter.getIntValue().equals(oppositeRuleParameter.getIntValue())) {
446 LOG.trace("Ethertype values are not equal, rule: {}, opposite rule: {} ", rule, oppositeRule);
452 // Check proto if exists. Values must be equal or missing
453 ParameterValue ruleProtoParameter = null;
454 ParameterValue oppositeRuleProtoParameter = null;
455 for (ParameterValue ruleParameter : ruleClassifierInstance.getParameterValue()) {
456 if (ruleParameter.getName().getValue().equals(IpProtoClassifierDefinition.PROTO_PARAM)) {
457 ruleProtoParameter = ruleParameter;
460 for (ParameterValue oppositeRuleParameter : oppositeRuleClassifierInstance.getParameterValue()) {
461 if (oppositeRuleParameter.getName().getValue().equals(IpProtoClassifierDefinition.PROTO_PARAM)) {
462 oppositeRuleProtoParameter = oppositeRuleParameter;
466 if (ruleProtoParameter == null || ruleProtoParameter.getIntValue() == null) {
468 } else if (oppositeRuleProtoParameter == null || oppositeRuleProtoParameter.getIntValue() == null) {
470 } else if (!ruleProtoParameter.getIntValue().equals(oppositeRuleProtoParameter.getIntValue())) {
471 LOG.trace("Proto parameters are not equal, rule parameters: {}, opposite rule parameters {} ",
472 ruleProtoParameter, oppositeRuleProtoParameter);
477 // TODO add support for port ranges
478 ParameterValue ruleL4Src = null;
479 ParameterValue oppositeRuleL4Src = null;
480 ParameterValue ruleL4Dst = null;
481 ParameterValue oppositeRuleL4Dst = null;
483 for (ParameterValue ruleParameter : ruleClassifierInstance.getParameterValue()) {
484 if (ruleParameter.getName().getValue().equals(L4ClassifierDefinition.SRC_PORT_PARAM)) {
485 ruleL4Src = ruleParameter;
487 if (ruleParameter.getName().getValue().equals(L4ClassifierDefinition.DST_PORT_PARAM)) {
488 ruleL4Dst = ruleParameter;
491 for (ParameterValue oppositeRuleParameter : oppositeRuleClassifierInstance.getParameterValue()) {
492 if (oppositeRuleParameter.getName().getValue().equals(L4ClassifierDefinition.SRC_PORT_PARAM)) {
493 oppositeRuleL4Src = oppositeRuleParameter;
495 if (oppositeRuleParameter.getName().getValue().equals(L4ClassifierDefinition.DST_PORT_PARAM)) {
496 oppositeRuleL4Dst = oppositeRuleParameter;
500 if (ruleL4Src == null && ruleL4Dst == null && oppositeRuleL4Src == null && oppositeRuleL4Dst == null) {
505 if (ruleL4Src == null && oppositeRuleL4Src != null) {
508 if (ruleL4Src != null && oppositeRuleL4Src == null) {
511 if (ruleL4Src != null && ruleL4Src.getIntValue() != null && oppositeRuleL4Src.getIntValue() != null
512 && ruleL4Src.equals(oppositeRuleL4Src)) {
515 if (ruleL4Src != null && ruleL4Src.getIntValue() != null && oppositeRuleL4Src.getIntValue() != null
516 && !ruleL4Src.equals(oppositeRuleL4Src)) {
521 if (ruleL4Dst == null && oppositeRuleL4Dst != null) {
524 if (ruleL4Dst != null && oppositeRuleL4Dst == null) {
527 if (ruleL4Dst != null && ruleL4Dst.getIntValue() != null && oppositeRuleL4Dst.getIntValue() != null
528 && ruleL4Dst.equals(oppositeRuleL4Dst)) {
531 if (ruleL4Dst != null && ruleL4Dst.getIntValue() != null && oppositeRuleL4Dst.getIntValue() != null
532 && !ruleL4Dst.equals(oppositeRuleL4Dst)) {
539 private void resolveDestinationEpgPolicy(OfWriter ofWriter, NetworkElements netElements, Policy reversedPolicy,
540 boolean isReverted) {
541 isReversedPolicy = true;
542 for (Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>> activeRulesByConstraints : getActiveRulesBetweenEps(
543 reversedPolicy, netElements.getSrcEp(), netElements.getDstEp())) {
544 Set<IpPrefix> sIpPrefixes = Policy.getIpPrefixesFrom(activeRulesByConstraints.getRowKey()
546 Set<IpPrefix> dIpPrefixes = Policy.getIpPrefixesFrom(activeRulesByConstraints.getColumnKey()
548 PolicyPair policyPair = new PolicyPair(netElements.getSrcEpOrdinals().getEpgId(), netElements.getDstEpOrdinals().getEpgId(),
549 netElements.getSrcEpOrdinals().getCgId(), netElements.getDstEpOrdinals().getCgId(), sIpPrefixes, dIpPrefixes,
550 netElements.getSrcNodeId(), netElements.getDstNodeId());
551 if (visitedReversePairs.contains(policyPair)) {
553 "PolicyEnforcer: Reverse: Already visited PolicyPair {}, endpoints {} {} skipped",
554 policyPair, netElements.getSrcEp().getKey(), netElements.getDstEp().getKey());
557 LOG.trace("PolicyEnforcer: Reverse: Visiting: PolicyPair {} via endpoints {} {}",
558 policyPair, netElements.getSrcEp().getKey(), netElements.getDstEp().getKey());
559 visitedReversePairs.add(policyPair);
562 int priority = 65000;
563 for (RuleGroup rg : activeRulesByConstraints.getValue()) {
564 TenantId tenantId = rg.getContractTenant().getId();
565 IndexedTenant tenant = ctx.getTenant(tenantId);
566 for (Rule rule : rg.getRules()) {
568 Set<Direction> directions = getRuleDirections(rule);
569 if (directions.isEmpty()) {
573 for(Direction direction : directions) {
575 // When specific direction flows exists, do not create them again
576 if (direction.equals(Direction.In) && reversePathFlowsCreated) {
579 if (direction.equals(Direction.Out) && directPathFlowsCreated) {
583 List<MatchBuilder> inMatches = createMatches(Direction.In, policyPair, tenant, rule);
584 List<MatchBuilder> outMatches = createMatches(Direction.Out, policyPair, tenant, rule);
586 // In case chain action is called here, it has to know that this is reversed policy to set tunnel
588 List<ActionBuilder> inActions = createActions(ofWriter, netElements, Direction.In, policyPair, tenant,
590 List<ActionBuilder> outActions = createActions(ofWriter, netElements, Direction.Out, policyPair, tenant,
593 createFlows(inMatches, inActions, netElements, ofWriter, priority);
594 createFlows(outMatches, outActions, netElements, ofWriter, priority);
596 if (direction.equals(Direction.In)) {
597 reversePathFlowsCreated = true;
599 if (direction.equals(Direction.Out)) {
600 directPathFlowsCreated = true;
605 if (directPathFlowsCreated && reversePathFlowsCreated) {
606 resolvedEpgPairs.put(netElements.getSrcEpg(), netElements.getDstEpg());
614 private void allowSameEpg(NodeId nodeId, OfWriter ofWriter) throws Exception {
615 for (Endpoint sourceEp : ctx.getEndpointManager().getEndpointsForNode(nodeId)) {
616 for (EgKey sourceEpgKey : ctx.getEndpointManager().getEgKeysForEndpoint(sourceEp)) {
618 IndexedTenant tenant = ctx.getTenant(sourceEpgKey.getTenantId());
619 if (tenant != null) {
620 EndpointGroup group = tenant.getEndpointGroup(sourceEpgKey.getEgId());
622 LOG.debug("EPG {} does not exit and is used in EP {}", sourceEpgKey, sourceEp.getKey());
625 IntraGroupPolicy igp = group.getIntraGroupPolicy();
627 if (igp == null || igp.equals(IntraGroupPolicy.Allow)) {
628 for (Endpoint dstEp : ctx.getEndpointManager().getEndpointsForGroup(sourceEpgKey)) {
629 EndpointFwdCtxOrdinals srcEpFwdCxtOrdinals =
630 OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, sourceEp);
631 if (srcEpFwdCxtOrdinals == null) {
632 LOG.debug("getEndpointFwdCtxOrdinals is null for EP {}", sourceEp);
636 EndpointFwdCtxOrdinals dstEpFwdCxtOrdinals =
637 OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, dstEp);
638 if (dstEpFwdCxtOrdinals == null) {
639 LOG.debug("getEndpointFwdCtxOrdinals is null for EP {}", dstEp);
643 int destinationEpgId = dstEpFwdCxtOrdinals.getEpgId();
644 int sourceEpgId = srcEpFwdCxtOrdinals.getEpgId();
645 ofWriter.writeFlow(nodeId, TABLE_ID, allowSameEpg(sourceEpgId, destinationEpgId));
646 ofWriter.writeFlow(nodeId, TABLE_ID, allowSameEpg(destinationEpgId, sourceEpgId));
654 // Return list of all rules with opposite direction
655 private List<Rule> findRulesInSameDirection(Rule ruleToResolve, List<Rule> reversedRules) {
656 List<Rule> sameDirectionRules = new ArrayList<>();
657 for (Rule ruleToCompare : reversedRules) {
658 for (ClassifierRef classifierRefToCompare : ruleToCompare.getClassifierRef()) {
659 for (ClassifierRef classifierRefToResolve : ruleToResolve.getClassifierRef()) {
660 if (isDirectionOpposite(classifierRefToCompare.getDirection(), classifierRefToResolve.getDirection())) {
661 sameDirectionRules.add(ruleToCompare);
666 return sameDirectionRules;
669 private boolean isDirectionOpposite(Direction one, Direction two) {
670 return ((one.equals(Direction.In) && two.equals(Direction.Out))
671 || (one.equals(Direction.Out) && two.equals(Direction.In)));
674 private List<Rule> getRules(List<Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>>> activeRules) {
675 List<Rule> rules = new ArrayList<>();
676 for (Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>> activeRule : activeRules) {
677 for (RuleGroup ruleGroup : activeRule.getValue()) {
678 for (Rule rule : ruleGroup.getRules()) {
686 private Flow createArpFlow(Integer fdId) {
688 Long etherType = FlowUtils.ARP;
689 // L2 Classifier so 20,000 for now
690 Integer priority = 20000;
692 MatchBuilder mb = new MatchBuilder().setEthernetMatch(FlowUtils.ethernetMatch(null, null, etherType));
694 addNxRegMatch(mb, RegMatch.of(NxmNxReg5.class, Long.valueOf(fdId)));
696 Match match = mb.build();
697 FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "arp", match);
698 return base().setPriority(priority)
701 .setInstructions(instructions(applyActionIns(nxOutputRegAction(NxmNxReg7.class))))
705 private Flow allowSameEpg(int sourceEpgId, int destinationEpgId) {
707 MatchBuilder mb = new MatchBuilder();
708 addNxRegMatch(mb, RegMatch.of(NxmNxReg0.class, (long) sourceEpgId),
709 RegMatch.of(NxmNxReg2.class, (long) destinationEpgId));
710 Match match = mb.build();
711 FlowId flowId = FlowIdUtils.newFlowId(TABLE_ID, "intraallow", match);
712 FlowBuilder flow = base().setId(flowId)
715 .setInstructions(instructions(applyActionIns(nxOutputRegAction(NxmNxReg7.class))));
719 private Flow allowFromTunnel(NodeConnectorId tunPort) {
721 MatchBuilder mb = new MatchBuilder().setInPort(tunPort);
722 addNxRegMatch(mb, RegMatch.of(NxmNxReg1.class, 0xffffffL));
723 Match match = mb.build();
724 FlowId flowId = FlowIdUtils.newFlowId(TABLE_ID, "tunnelallow", match);
725 FlowBuilder flow = base().setId(flowId)
728 .setInstructions(instructions(applyActionIns(nxOutputRegAction(NxmNxReg7.class))));
733 private List<MatchBuilder> createMatches(Direction direction, PolicyPair policyPair, IndexedTenant contractTenant,
735 Map<String, ParameterValue> paramsFromClassifier = new HashMap<>();
736 Set<ClassifierDefinitionId> classifiers = new HashSet<>();
737 for (ClassifierRef cr : rule.getClassifierRef()) {
739 if (cr.getDirection() != null && !cr.getDirection().equals(Direction.Bidirectional)
740 && !cr.getDirection().equals(direction)) {
744 // XXX - TODO - implement connection tracking (requires openflow
745 // extension and data plane support - in 2.4. Will need to handle
746 // case where we are working with mix of nodes.
748 ClassifierInstance ci = contractTenant.getClassifier(cr.getInstanceName());
750 // XXX TODO fail the match and raise an exception
751 LOG.warn("Classifier instance {} not found", cr.getInstanceName().getValue());
754 Classifier classifier = SubjectFeatures.getClassifier(ci.getClassifierDefinitionId());
755 if (classifier == null) {
756 // XXX TODO fail the match and raise an exception
757 LOG.warn("Classifier definition {} not found", ci.getClassifierDefinitionId().getValue());
760 classifiers.add(new ClassifierDefinitionId(ci.getClassifierDefinitionId()));
761 for (ParameterValue v : ci.getParameterValue()) {
762 if (paramsFromClassifier.get(v.getName().getValue()) == null) {
763 if (v.getIntValue() != null || v.getStringValue() != null || v.getRangeValue() != null) {
764 paramsFromClassifier.put(v.getName().getValue(), v);
767 if (!paramsFromClassifier.get(v.getName().getValue()).equals(v)) {
768 throw new IllegalArgumentException("Classification error in rule: " + rule.getName()
769 + ".\nCause: " + "Classification conflict detected at parameter " + v.getName());
774 if (classifiers.isEmpty()) {
777 List<Map<String, ParameterValue>> derivedParamsByName = ParamDerivator.ETHER_TYPE_DERIVATOR.deriveParameter(paramsFromClassifier);
778 List<MatchBuilder> flowMatchBuilders = new ArrayList<>();
779 for (Map<String, ParameterValue> params : derivedParamsByName) {
780 List<MatchBuilder> matchBuildersToResolve = new ArrayList<>();
781 if (policyPair.consumerEicIpPrefixes.isEmpty() && policyPair.providerEicIpPrefixes.isEmpty()) {
782 matchBuildersToResolve.add(createBaseMatch(direction, policyPair, null, null));
783 } else if (!policyPair.consumerEicIpPrefixes.isEmpty() && policyPair.providerEicIpPrefixes.isEmpty()) {
784 for (IpPrefix sIpPrefix : policyPair.consumerEicIpPrefixes) {
785 matchBuildersToResolve.add(createBaseMatch(direction, policyPair, sIpPrefix, null));
787 } else if (policyPair.consumerEicIpPrefixes.isEmpty() && !policyPair.providerEicIpPrefixes.isEmpty()) {
788 for (IpPrefix dIpPrefix : policyPair.consumerEicIpPrefixes) {
789 matchBuildersToResolve.add(createBaseMatch(direction, policyPair, null, dIpPrefix));
792 for (IpPrefix sIpPrefix : policyPair.consumerEicIpPrefixes) {
793 for (IpPrefix dIpPrefix : policyPair.consumerEicIpPrefixes) {
794 matchBuildersToResolve.add(createBaseMatch(direction, policyPair, sIpPrefix, dIpPrefix));
798 for (ClassifierDefinitionId clDefId : classifiers) {
799 Classifier classifier = SubjectFeatures.getClassifier(clDefId);
800 ClassificationResult result = classifier.updateMatch(matchBuildersToResolve, params);
801 if (!result.isSuccessfull()) {
802 // TODO consider different handling.
803 throw new IllegalArgumentException("Classification conflict detected in rule: " + rule.getName()
804 + ".\nCause: " + result.getErrorMessage());
806 matchBuildersToResolve = new ArrayList<>(result.getMatchBuilders());
808 flowMatchBuilders.addAll(matchBuildersToResolve);
810 return flowMatchBuilders;
813 private List<ActionBuilder> createActions(OfWriter ofWriter, NetworkElements netElements, Direction direction, PolicyPair policyPair,
814 IndexedTenant contractTenant, Rule rule, boolean isReversedDirection) {
815 List<ActionBuilder> actionBuilderList = new ArrayList<>();
816 if (rule.getActionRef() != null) {
818 // Pre-sort by references using order, then name
819 List<ActionRef> actionRefList = new ArrayList<>(rule.getActionRef());
820 Collections.sort(actionRefList, ActionRefComparator.INSTANCE);
822 for (ActionRef actionRule : actionRefList) {
823 ActionInstance actionInstance = contractTenant.getAction(actionRule.getName());
824 if (actionInstance == null) {
825 // XXX TODO fail the match and raise an exception
826 LOG.warn("Action instance {} not found", actionRule.getName().getValue());
829 Action action = SubjectFeatures.getAction(actionInstance.getActionDefinitionId());
830 if (action == null) {
831 // XXX TODO fail the match and raise an exception
832 LOG.warn("Action definition {} not found", actionInstance.getActionDefinitionId().getValue());
836 Map<String, Object> params = new HashMap<>();
837 if (actionInstance.getParameterValue() != null) {
838 for (ParameterValue v : actionInstance.getParameterValue()) {
839 if (v.getName() == null)
841 if (v.getIntValue() != null) {
842 params.put(v.getName().getValue(), v.getIntValue());
843 } else if (v.getStringValue() != null) {
844 params.put(v.getName().getValue(), v.getStringValue());
848 if (isReversedDirection) {
849 direction = reverse(direction);
852 // Convert the GBP Action to one or more OpenFlow Actions
853 if (!(actionRefList.indexOf(actionRule) == (actionRefList.size() - 1)
854 && action.equals(SubjectFeatures.getAction(AllowActionDefinition.DEFINITION.getId())))) {
855 actionBuilderList = action.updateAction(actionBuilderList, params, actionRule.getOrder(), netElements,
856 policyPair, ofWriter, ctx, direction);
861 return actionBuilderList;
864 private Direction reverse(Direction direction) {
865 if (direction.equals(Direction.In)) {
866 return Direction.Out;
868 else if(direction.equals(Direction.Out)) {
872 return Direction.Bidirectional;
876 private void createFlows(List<MatchBuilder> flowMatchBuilders, List<ActionBuilder> actionBuilderList, NetworkElements netElements,
877 OfWriter ofWriter, int priority) {
878 FlowBuilder flow = base().setPriority(priority);
879 if(flowMatchBuilders == null) {
882 for (MatchBuilder mb : flowMatchBuilders) {
883 Match match = mb.build();
884 FlowId flowId = FlowIdUtils.newFlowId(TABLE_ID, "cg", match);
885 flow.setMatch(match).setId(flowId).setPriority(priority);
887 // If destination is External, the last Action ALLOW must be changed to goto
888 // NAT/External table.
889 // If actionBuilderList is empty (we removed the last Allow) then go straight to
890 // ExternalMapper table.
892 List<ExternalImplicitGroup> eigs = ctx.getTenant(netElements.getDstEp().getTenant())
895 .getExternalImplicitGroup();
896 boolean performNat = false;
897 for (EndpointL3 natEp : ctx.getEndpointManager().getL3EndpointsWithNat()) {
898 if (natEp.getMacAddress() != null &&
899 natEp.getL2Context() != null &&
900 netElements.getSrcEp().getKey().equals(new EndpointKey(natEp.getL2Context(),
901 natEp.getMacAddress())) &&
902 EndpointManager.isExternal(netElements.getDstEp(), eigs)) {
907 if (actionBuilderList == null) {
908 //TODO - analyse, what happen for unknown action, SFC, etc.
909 LOG.warn("Action builder list not found, partially flow which is not created: {}", flow.build());
912 if (actionBuilderList.isEmpty()) {
913 flow.setInstructions((performNat == true) ? instructions(gotoEgressNatInstruction) : instructions(gotoExternalInstruction));
915 flow.setInstructions(instructions(applyActionIns(actionBuilderList),
916 (performNat == true) ? gotoEgressNatInstruction : gotoExternalInstruction));
918 ofWriter.writeFlow(netElements.getLocalNodeId(), TABLE_ID, flow.build());
922 private MatchBuilder createBaseMatch(Direction direction, PolicyPair policyPair, IpPrefix sIpPrefix,
923 IpPrefix dIpPrefix) {
924 MatchBuilder baseMatch = new MatchBuilder();
925 if (direction.equals(Direction.In)) {
926 addNxRegMatch(baseMatch, RegMatch.of(NxmNxReg0.class, (long) policyPair.consumerEpgId),
927 RegMatch.of(NxmNxReg1.class, (long) policyPair.consumerCondGrpId),
928 RegMatch.of(NxmNxReg2.class, (long) policyPair.providerEpgId),
929 RegMatch.of(NxmNxReg3.class, (long) policyPair.providerCondGrpId));
930 if (sIpPrefix != null) {
931 baseMatch.setLayer3Match(createLayer3Match(sIpPrefix, true));
933 if (dIpPrefix != null) {
934 baseMatch.setLayer3Match(createLayer3Match(dIpPrefix, true));
937 addNxRegMatch(baseMatch, RegMatch.of(NxmNxReg0.class, (long) policyPair.providerEpgId),
938 RegMatch.of(NxmNxReg1.class, (long) policyPair.providerCondGrpId),
939 RegMatch.of(NxmNxReg2.class, (long) policyPair.consumerEpgId),
940 RegMatch.of(NxmNxReg3.class, (long) policyPair.consumerCondGrpId));
941 if (sIpPrefix != null) {
942 baseMatch.setLayer3Match(createLayer3Match(sIpPrefix, false));
944 if (dIpPrefix != null) {
945 baseMatch.setLayer3Match(createLayer3Match(dIpPrefix, false));
951 private Layer3Match createLayer3Match(IpPrefix ipPrefix, boolean isSrc) {
952 if (ipPrefix.getIpv4Prefix() != null) {
954 return new Ipv4MatchBuilder().setIpv4Source(ipPrefix.getIpv4Prefix()).build();
956 return new Ipv4MatchBuilder().setIpv4Destination(ipPrefix.getIpv4Prefix()).build();
960 return new Ipv6MatchBuilder().setIpv6Source(ipPrefix.getIpv6Prefix()).build();
962 return new Ipv6MatchBuilder().setIpv6Destination(ipPrefix.getIpv6Prefix()).build();
967 // TODO: move to a common utils for all renderers
968 private List<Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>>> getActiveRulesBetweenEps(Policy policy,
969 Endpoint consEp, Endpoint provEp) {
970 List<Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>>> rulesWithEpConstraints = new ArrayList<>();
971 for (Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>> cell : policy.getRuleMap().cellSet()) {
972 EndpointConstraint consEpConstraint = cell.getRowKey();
973 EndpointConstraint provEpConstraint = cell.getColumnKey();
974 if (epMatchesConstraint(consEp, consEpConstraint) && epMatchesConstraint(provEp, provEpConstraint)) {
975 rulesWithEpConstraints.add(cell);
978 return rulesWithEpConstraints;
981 private boolean epMatchesConstraint(Endpoint ep, EndpointConstraint constraint) {
982 List<ConditionName> epConditions = Collections.emptyList();
983 if (ep.getCondition() != null) {
984 epConditions = ep.getCondition();
986 return constraint.getConditionSet().matches(epConditions);
989 private enum PathStatus { both, partial, none }
991 public static boolean checkPolicyOrientation() {
992 return isReversedPolicy;
996 * Private internal class for ordering Actions in Rules. The order is
997 * determined first by the value of the order parameter, with the lower
998 * order actions being applied first; for Actions with either the same order
999 * or no order, ordering is lexicographical by name.
1001 private static class ActionRefComparator implements Comparator<ActionRef> {
1003 public static final ActionRefComparator INSTANCE = new ActionRefComparator();
1006 public int compare(ActionRef arg0, ActionRef arg1) {
1007 return ComparisonChain.start()
1008 .compare(arg0.getOrder(), arg1.getOrder(), Ordering.natural().nullsLast())
1009 .compare(arg0.getName().getValue(), arg1.getName().getValue(), Ordering.natural().nullsLast())
1016 public static class PolicyPair {
1018 private final int consumerEpgId;
1019 private final int providerEpgId;
1020 private final int consumerCondGrpId;
1021 private final int providerCondGrpId;
1022 private final Set<IpPrefix> consumerEicIpPrefixes;
1023 private final Set<IpPrefix> providerEicIpPrefixes;
1024 private final NodeId consumerEpNodeId;
1025 private final NodeId providerEpNodeId;
1027 public PolicyPair(int consumerEpgId, int providerEpgId, int consumerCondGrpId, int providerCondGrpId,
1028 Set<IpPrefix> consumerEicIpPrefixes, Set<IpPrefix> providerEicIpPrefixes, NodeId consumerEpNodeId, NodeId providerEpNodeId) {
1030 this.consumerEpgId = consumerEpgId;
1031 this.providerEpgId = providerEpgId;
1032 this.consumerCondGrpId = consumerCondGrpId;
1033 this.providerCondGrpId = providerCondGrpId;
1034 this.consumerEicIpPrefixes = consumerEicIpPrefixes;
1035 this.providerEicIpPrefixes = providerEicIpPrefixes;
1036 this.consumerEpNodeId = consumerEpNodeId;
1037 this.providerEpNodeId = providerEpNodeId;
1040 public int getConsumerEpgId() {
1041 return consumerEpgId;
1044 public int getProviderEpgId() {
1045 return providerEpgId;
1048 public NodeId getConsumerEpNodeId() {
1049 return consumerEpNodeId;
1052 public NodeId getProviderEpNodeId() {
1053 return providerEpNodeId;
1057 public int hashCode() {
1058 final int prime = 31;
1060 result = prime * result + ((providerEicIpPrefixes == null) ? 0 : providerEicIpPrefixes.hashCode());
1061 result = prime * result + providerCondGrpId;
1062 result = prime * result + providerEpgId;
1063 result = prime * result + ((consumerEicIpPrefixes == null) ? 0 : consumerEicIpPrefixes.hashCode());
1064 result = prime * result + consumerCondGrpId;
1065 result = prime * result + consumerEpgId;
1066 result = prime * result + ((consumerEpNodeId == null) ? 0 : consumerEpNodeId.hashCode());
1067 result = prime * result + ((providerEpNodeId == null) ? 0 : providerEpNodeId.hashCode());
1073 public boolean equals(Object obj) {
1078 if (getClass() != obj.getClass())
1080 PolicyPair other = (PolicyPair) obj;
1081 if (providerEicIpPrefixes == null) {
1082 if (other.providerEicIpPrefixes != null) {
1085 } else if (!providerEicIpPrefixes.equals(other.providerEicIpPrefixes)) {
1088 if (consumerEicIpPrefixes == null) {
1089 if (other.consumerEicIpPrefixes != null) {
1092 } else if (!consumerEicIpPrefixes.equals(other.consumerEicIpPrefixes)) {
1095 if (consumerEpNodeId == null) {
1096 if (other.consumerEpNodeId != null) {
1099 } else if (!consumerEpNodeId.getValue().equals(other.consumerEpNodeId.getValue())) {
1102 if (providerEpNodeId == null) {
1103 if (other.providerEpNodeId != null) {
1106 } else if (!providerEpNodeId.getValue().equals(other.providerEpNodeId.getValue())) {
1109 return (providerCondGrpId == other.providerCondGrpId)
1110 && (providerEpgId == other.providerEpgId)
1111 && (consumerCondGrpId == other.consumerCondGrpId)
1112 && (consumerEpgId == other.consumerEpgId);
1117 public String toString() {
1118 return "consumerEPG: " + consumerEpgId +
1119 "consumerCG: " + consumerCondGrpId +
1120 "providerEPG: " + providerEpgId +
1121 "providerCG: " + providerCondGrpId +
1122 "consumerEpNodeId: " + consumerEpNodeId +
1123 "providerEpNodeId: " + providerEpNodeId +
1124 "consumerEicIpPrefixes: " + consumerEicIpPrefixes +
1125 "providerEicIpPrefixes: " + providerEicIpPrefixes;
1129 public class NetworkElements {
1131 private final Endpoint srcEp;
1132 private final Endpoint dstEp;
1133 private final EgKey srcEpg;
1134 private final EgKey dstEpg;
1135 private NodeId srcNodeId;
1136 private NodeId dstNodeId;
1137 private final NodeId localNodeId;
1138 private EndpointFwdCtxOrdinals srcEpOrdinals;
1139 private EndpointFwdCtxOrdinals dstEpOrdinals;
1141 public NetworkElements(Endpoint srcEp, Endpoint dstEp, EgKey srcEpg, EgKey dstEpg, NodeId nodeId, OfContext ctx) throws Exception {
1144 this.srcEpg = srcEpg;
1145 this.dstEpg = dstEpg;
1146 this.localNodeId = nodeId;
1147 this.srcEpOrdinals = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, srcEp);
1148 if (this.srcEpOrdinals == null) {
1149 LOG.debug("getEndpointFwdCtxOrdinals is null for EP {}", srcEp);
1152 this.dstEpOrdinals = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, dstEp);
1153 if (this.dstEpOrdinals == null) {
1154 LOG.debug("getEndpointFwdCtxOrdinals is null for EP {}", dstEp);
1157 if (dstEp.getAugmentation(OfOverlayContext.class) != null) {
1158 this.dstNodeId = dstEp.getAugmentation(OfOverlayContext.class).getNodeId();
1160 if (srcEp.getAugmentation(OfOverlayContext.class) != null) {
1161 this.srcNodeId = srcEp.getAugmentation(OfOverlayContext.class).getNodeId();
1166 public Endpoint getSrcEp() {
1171 public Endpoint getDstEp() {
1175 public EgKey getSrcEpg() {
1179 public EgKey getDstEpg() {
1183 public NodeId getSrcNodeId() {
1188 public NodeId getDstNodeId() {
1193 public NodeId getLocalNodeId() {
1198 public EndpointFwdCtxOrdinals getSrcEpOrdinals() {
1199 return srcEpOrdinals;
1203 public EndpointFwdCtxOrdinals getDstEpOrdinals() {
1204 return dstEpOrdinals;