Implementing DHCP proxy command for VPP
[groupbasedpolicy.git] / renderers / ios-xe / src / main / java / org / opendaylight / groupbasedpolicy / renderer / ios_xe_provider / impl / util / PolicyManagerUtil.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util;
10
11 import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl.ActionCase.CHAIN;
12
13 import com.google.common.base.Preconditions;
14 import com.google.common.collect.Iterables;
15 import com.google.common.util.concurrent.Futures;
16 import com.google.common.util.concurrent.ListenableFuture;
17 import java.util.ArrayList;
18 import java.util.Collection;
19 import java.util.Collections;
20 import java.util.HashMap;
21 import java.util.HashSet;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Optional;
25 import java.util.Set;
26 import java.util.concurrent.TimeUnit;
27 import javax.annotation.Nonnull;
28 import javax.annotation.Nullable;
29 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
30 import org.opendaylight.groupbasedpolicy.api.sf.ChainActionDefinition;
31 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyConfigurationContext;
32 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl;
33 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl.ActionCase;
34 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.writer.PolicyWriterUtil;
35 import org.opendaylight.groupbasedpolicy.sxp.ep.provider.api.EPToSgtMapper;
36 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePath;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
38 import org.opendaylight.yang.gen.v1.urn.ios.rev160308.ClassNameType;
39 import org.opendaylight.yang.gen.v1.urn.ios.rev160308.PolicyActionType;
40 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.SecurityGroup;
41 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.SecurityGroupBuilder;
42 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.Destination;
43 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.DestinationBuilder;
44 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.Source;
45 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.SourceBuilder;
46 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.ServicePolicy;
47 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.ServicePolicyBuilder;
48 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.TypeBuilder;
49 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.type.ServiceChain.Direction;
50 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.type.ServiceChainBuilder;
51 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMap;
52 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMapBuilder;
53 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMapKey;
54 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMap;
55 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMapBuilder;
56 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMapKey;
57 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._class.map.Match;
58 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._class.map.MatchBuilder;
59 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.Class;
60 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.ClassBuilder;
61 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.ClassKey;
62 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.ActionList;
63 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.ActionListBuilder;
64 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.ActionListKey;
65 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.ForwardCaseBuilder;
66 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.forward._case.ForwardBuilder;
67 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.forward._case.forward.ServicePath;
68 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.forward._case.forward.ServicePathBuilder;
69 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.forward._case.forward.ServicePathKey;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.AddressEndpointKey;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.AbsoluteLocation;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.LocationType;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCase;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionDefinitionId;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.RuleName;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.IpPrefixType;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.EndpointPolicyParticipation;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.rule.group.with.renderer.endpoint.participation.RuleGroupWithRendererEndpointParticipation;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.Configuration;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpoint;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.renderer.endpoint.PeerEndpoint;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.rule.groups.RuleGroup;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.actions.Action;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.classifiers.Classifier;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.resolved.rules.ResolvedRule;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.ip.sgt.distribution.rev160715.rpc.fields.Binding;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.ip.sgt.distribution.rev160715.rpc.fields.BindingBuilder;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.ip.sgt.distribution.rev160715.rpc.fields.binding.PeerNodeBuilder;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
95 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
96 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
97 import org.slf4j.Logger;
98 import org.slf4j.LoggerFactory;
99
100 public class PolicyManagerUtil {
101
102     private static final Logger LOG = LoggerFactory.getLogger(PolicyManagerUtil.class);
103
104     private PolicyManagerUtil() {
105         throw new IllegalAccessError("instance of util class not supported");
106     }
107
108     /**
109      * Main method for policy creation which looks for all actions specified in rules between two endpoints. Whichever
110      * action has been found, it is resolved (only chain action is supported for now).
111      *
112      * @param sourceSgt      - security group tag of source endpoint
113      * @param destinationSgt - security group tag of destination endpoint
114      * @param context        - stores info about location of classifier/policy-map and status
115      * @param data           - new data, used to found appropriate rule group
116      * @param peerEndpoint   - contains info about rule groups between endpoint pairs
117      * @param dataBroker     - data provider for odl controller
118      */
119     public static void syncEndpointPairCreatePolicy(final Sgt sourceSgt, final Sgt destinationSgt,
120                                                     final PolicyConfigurationContext context, final Configuration data,
121                                                     final PeerEndpoint peerEndpoint, final DataBroker dataBroker) {
122         // Create appropriate policy map
123         if (! PolicyManagerUtil.constructEmptyPolicyMapWithInterface(context)) {
124             final String policyMapName = context.getPolicyMapLocation().getPolicyMapName();
125             final String interfaceName = context.getPolicyMapLocation().getInterfaceName();
126             final String info = String.format("Unable to create policy-map %s on interface %s", policyMapName, interfaceName);
127             context.appendUnconfiguredRendererEP(StatusUtil.assembleFullyNotConfigurableRendererEP(context, info));
128             LOG.warn(info);
129             return;
130         }
131
132         // Find actions from acquired data
133         final Map<ActionCase, ActionInDirection> actionMap = PolicyManagerUtil.getActionInDirection(data, peerEndpoint);
134         if (actionMap.isEmpty()) {
135             LOG.debug("No usable action found for EP-sgt[{}] | peerEP-sgt[{}]", sourceSgt, destinationSgt);
136             return;
137         }
138
139         // Chain action
140         if (actionMap.containsKey(ActionCase.CHAIN)) {
141             ServiceChainingUtil.newChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap, context,
142                     dataBroker);
143         }
144     }
145
146     /**
147      * Method for policy removal which looks for all actions specified in rules between two endpoints. Whichever
148      * action has been found, it is resolved (only chain action is supported).
149      *
150      * @param sourceSgt      - security group tag of source endpoint
151      * @param destinationSgt - security group tag of destination endpoint
152      * @param context        - stores info about location of classifier/policy-map and status
153      * @param data           - data used to identify all elements marked to remove
154      * @param peerEndpoint   - contains info about rule groups between endpoint pairs
155      */
156     public static void syncEndpointPairRemovePolicy(final Sgt sourceSgt, final Sgt destinationSgt,
157                                                     final PolicyConfigurationContext context, final Configuration data,
158                                                     final PeerEndpoint peerEndpoint) {
159         // Find actions from acquired data
160         final Map<ActionCase, ActionInDirection> actionMap = PolicyManagerUtil.getActionInDirection(data, peerEndpoint);
161         if (actionMap.isEmpty()) {
162             LOG.debug("no usable action found for EP-sgt[{}] | peerEP-sgt[{}]",
163                     sourceSgt, destinationSgt);
164             return;
165         }
166
167         // Chain action
168         if (actionMap.containsKey(ActionCase.CHAIN)) {
169             ServiceChainingUtil.resolveRemovedChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap,
170                     context);
171         }
172
173         // Remove policy-map if empty
174         if (! deleteEmptyPolicyMapWithInterface(context.getPolicyMapLocation())) {
175             final PolicyManagerImpl.PolicyMapLocation location = context.getPolicyMapLocation();
176             final String info = String.format("Unable to remove policy-map %s and interface %s", location.getPolicyMapName(),
177                     location.getInterfaceName());
178             LOG.warn(info);
179         }
180     }
181
182     /**
183      * According to info from {@link RuleGroupWithRendererEndpointParticipation} (composite key) finds appropriate subject
184      *
185      * @param data                       - contains all rule groups
186      * @param ruleGroupWithParticipation - contains info about how to find right rule group
187      * @return rule group if found, null otherwise
188      */
189     @Nullable
190     private static RuleGroup findRuleGroup(final Configuration data,
191                                            final RuleGroupWithRendererEndpointParticipation ruleGroupWithParticipation) {
192         final TenantId tenantId = ruleGroupWithParticipation.getTenantId();
193         final ContractId contractId = ruleGroupWithParticipation.getContractId();
194         final SubjectName subjectName = ruleGroupWithParticipation.getSubjectName();
195         for (RuleGroup ruleGroup : data.getRuleGroups().getRuleGroup()) {
196             if (! ruleGroup.getTenantId().equals(tenantId)) {
197                 continue;
198             }
199             if (! ruleGroup.getContractId().equals(contractId)) {
200                 continue;
201             }
202             if (ruleGroup.getSubjectName().equals(subjectName)) {
203                 return ruleGroup;
204             }
205         }
206         return null;
207     }
208
209     @Nullable
210     public static Sgt findSgtTag(final EPToSgtMapper sxpEpProvider, final AddressEndpointKey endpointKey,
211                                  final List<AddressEndpointWithLocation> endpointsWithLocation, final long timeout, final TimeUnit unit) {
212         if (endpointKey == null || endpointsWithLocation == null) {
213             return null;
214         }
215         final AddressEndpointWithLocation endpointWithLocation = RendererPolicyUtil.lookupEndpoint(endpointKey,
216                 endpointsWithLocation);
217
218         final ListenableFuture<Collection<Sgt>> sgtForEPFu = sxpEpProvider.findSgtForEP(endpointWithLocation);
219
220         Sgt sgt = null;
221         try {
222             sgt = Iterables.getFirst(sgtForEPFu.get(timeout, unit), null);
223             LOG.trace("For ep[{}] found sgt: {}", endpointKey, sgt);
224         } catch (Exception e) {
225             LOG.debug("failed to obtain sgt for given endpoint: ", e.getMessage());
226         }
227
228         return sgt;
229     }
230
231     /**
232      * Creates empty policy-map if does not exist and bounds it to interface if it is not. If policy-map exists, method
233      * checks whether it is connected to correct interface and creates it if necessary. If policy-map does not exist,
234      * it is created with particular interface
235      *
236      * @param context - all data required to create/localize policy-map
237      * @return true if policy-map and interface is present/written on the device, false otherwise
238      */
239     private static boolean constructEmptyPolicyMapWithInterface(final PolicyConfigurationContext context) {
240         final PolicyManagerImpl.PolicyMapLocation policyMapLocation = context.getPolicyMapLocation();
241         final String policyMapName = policyMapLocation.getPolicyMapName();
242         final DataBroker mountpoint = policyMapLocation.getMountpoint();
243         final String interfaceName = policyMapLocation.getInterfaceName();
244         final NodeId nodeId = policyMapLocation.getNodeId();
245         final InstanceIdentifier<PolicyMap> policyMapIid = PolicyWriterUtil.policyMapInstanceIdentifier(policyMapName);
246         final Optional<PolicyMap> optionalPolicyMap =
247                 Optional.ofNullable(PolicyWriterUtil.netconfRead(mountpoint, policyMapIid));
248         if (optionalPolicyMap.isPresent()) {
249             LOG.trace("Policy map with name {} on interface {} already exists", policyMapName, interfaceName);
250             final InstanceIdentifier<ServicePolicy> servicePolicyIid = PolicyWriterUtil.interfaceInstanceIdentifier(interfaceName);
251             final Optional<ServicePolicy> optionalServicePolicy =
252                     Optional.ofNullable(PolicyWriterUtil.netconfRead(mountpoint, servicePolicyIid));
253             if (optionalServicePolicy.isPresent()) {
254                 LOG.trace("Policy map {} is bound to correct interface {} ", policyMapName, interfaceName);
255                 return true;
256             } else {
257                 boolean iResult = PolicyWriterUtil.writeInterface(context.getPolicyMapLocation());
258                 context.setFutureResult(Futures.immediateCheckedFuture(iResult));
259                 return iResult;
260             }
261         } else {
262             final PolicyMap emptyMap = createEmptyPolicyMap(policyMapName);
263             boolean pmResult = PolicyWriterUtil.writePolicyMap(emptyMap, context.getPolicyMapLocation());
264             context.setFutureResult(Futures.immediateCheckedFuture(pmResult));
265             if (pmResult) {
266                 LOG.info("Created policy-map {} on node {}", policyMapName, nodeId.getValue());
267                 LOG.trace("Adding policy-map {} to interface {}", policyMapName, interfaceName);
268                 boolean iResult = PolicyWriterUtil.writeInterface(context.getPolicyMapLocation());
269                 context.setFutureResult(Futures.immediateCheckedFuture(iResult));
270                 return iResult;
271             }
272             return false;
273         }
274     }
275
276     /**
277      * Removes empty policy-map and its interface
278      *
279      * @param policyMapLocation - location of policy-map
280      * @return true if policy-map is present and not empty or if it is successfully removed also with interface, false
281      * otherwise
282      */
283     private static boolean deleteEmptyPolicyMapWithInterface(PolicyManagerImpl.PolicyMapLocation policyMapLocation) {
284         final String policyMapName = policyMapLocation.getPolicyMapName();
285         final DataBroker mountpoint = policyMapLocation.getMountpoint();
286         final InstanceIdentifier<PolicyMap> policyMapIid = PolicyWriterUtil.policyMapInstanceIdentifier(policyMapName);
287         // Read policy map
288         final Optional<PolicyMap> optionalPolicyMap = Optional.ofNullable(PolicyWriterUtil.netconfRead(mountpoint, policyMapIid));
289         if (optionalPolicyMap.isPresent()) {
290             final PolicyMap policyMap = optionalPolicyMap.get();
291             if (policyMap.getXmlClass() == null || policyMap.getXmlClass().isEmpty()) {
292                 // No entries, remove
293                 if (PolicyWriterUtil.removePolicyMap(policyMapLocation)) {
294                     // Remove interface binding if exists
295                     LOG.info("Policy-map {} removed", policyMapName);
296                     return PolicyWriterUtil.removeInterface(policyMapLocation);
297                 }
298                 return false;
299             }
300             LOG.debug("Policy-map {} still contains entries, cannot be removed", policyMapLocation.getPolicyMapName());
301             return true;
302         }
303         return true;
304
305     }
306
307     public static ServicePolicy createServicePolicy(final String chainName, final Direction direction) {
308         // Service Chain
309         final ServiceChainBuilder serviceChainBuilder = new ServiceChainBuilder();
310         serviceChainBuilder.setName(chainName) // Same as the policy map name
311                 .setDirection(direction);
312         // Service policy
313         final TypeBuilder typeBuilder = new TypeBuilder();
314         typeBuilder.setServiceChain(serviceChainBuilder.build());
315         // Service Policy
316         ServicePolicyBuilder servicePolicyBuilder = new ServicePolicyBuilder();
317         servicePolicyBuilder.setType(typeBuilder.build());
318
319         return servicePolicyBuilder.build();
320     }
321
322     private static PolicyMap createEmptyPolicyMap(String policyMapName) {
323         // TODO maybe could be better to create also class-default entry with pass-through value than not to create any default entry at all
324         // Construct policy map
325         final PolicyMapBuilder policyMapBuilder = new PolicyMapBuilder();
326         policyMapBuilder.setName(policyMapName)
327                 .setKey(new PolicyMapKey(policyMapName))
328                 .setType(PolicyMap.Type.ServiceChain);
329         return policyMapBuilder.build();
330     }
331
332     static Class createPolicyMapEntry(final String policyClassName, final RenderedServicePath renderedPath,
333                                       final ActionCase actionCase) {
334         // Forward Case
335         final ForwardCaseBuilder forwardCaseBuilder = new ForwardCaseBuilder();
336         if (actionCase.equals(CHAIN) && renderedPath != null) {
337             // Chain Action
338             final ForwardBuilder forwardBuilder = new ForwardBuilder();
339             final List<ServicePath> servicePaths = new ArrayList<>();
340             final ServicePathBuilder servicePathBuilder = new ServicePathBuilder();
341             servicePathBuilder.setKey(new ServicePathKey(renderedPath.getPathId()))
342                     .setServicePathId(renderedPath.getPathId())
343                     .setServiceIndex(renderedPath.getStartingIndex());
344             servicePaths.add(servicePathBuilder.build());
345             forwardBuilder.setServicePath(servicePaths);
346             forwardCaseBuilder.setForward(forwardBuilder.build());
347         }
348         // Create Action List
349         final List<ActionList> actionList = new ArrayList<>();
350         final ActionListBuilder actionListBuilder = new ActionListBuilder();
351         actionListBuilder.setKey(new ActionListKey(PolicyActionType.Forward))
352                 .setActionType(PolicyActionType.Forward)
353                 .setActionParam(forwardCaseBuilder.build());
354         actionList.add(actionListBuilder.build());
355         // Build class entry
356         final ClassBuilder policyClassBuilder = new ClassBuilder();
357         policyClassBuilder.setName(new ClassNameType(policyClassName))
358                 .setKey(new ClassKey(new ClassNameType(policyClassName)))
359                 .setActionList(actionList);
360         return policyClassBuilder.build();
361     }
362
363     static Match createSecurityGroupMatch(final int sourceTag, final int destinationTag) {
364         final SecurityGroupBuilder sgBuilder = new SecurityGroupBuilder();
365         final Source source = new SourceBuilder().setTag(sourceTag).build();
366         final Destination destination = new DestinationBuilder().setTag(destinationTag).build();
367         sgBuilder.setDestination(destination)
368                 .setSource(source);
369         final SecurityGroup securityGroup = sgBuilder.build();
370         final MatchBuilder matchBuilder = new MatchBuilder();
371         matchBuilder.setSecurityGroup(securityGroup);
372         return matchBuilder.build();
373     }
374
375     @Nonnull
376     static ClassMap createClassMap(final String classMapName, final Match match) {
377         final ClassMapBuilder cmBuilder = new ClassMapBuilder();
378         cmBuilder.setName(classMapName)
379                 .setKey(new ClassMapKey(classMapName))
380                 .setPrematch(ClassMap.Prematch.MatchAll)
381                 .setMatch(match);
382         return cmBuilder.build();
383     }
384
385     /**
386      * Constructs {@link ActionInDirection} object with {@link ActionCase} as a key. ActionInDirection object contains
387      * info about action, participation and rule direction.
388      *
389      * @param data - used for finding rule's rule group
390      * @param peer - contains {@link RuleGroupWithRendererEndpointParticipation}
391      * @return map with actionCase/ActionInDirection entries, empty map if no rule is found
392      */
393     @Nonnull
394     private static Map<ActionCase, ActionInDirection> getActionInDirection(final Configuration data,
395                                                                            final PeerEndpoint peer) {
396         final Set<ResolvedRule> rulesInDirection = new HashSet<>();
397         EndpointPolicyParticipation participation = null;
398         HasDirection.Direction direction = null;
399         // Find all rules in desired direction
400         for (RuleGroupWithRendererEndpointParticipation ruleGroupKey :
401                 peer.getRuleGroupWithRendererEndpointParticipation()) {
402             participation = ruleGroupKey.getRendererEndpointParticipation();
403             final RuleGroup ruleGroup = findRuleGroup(data, ruleGroupKey);
404             if (ruleGroup == null || ruleGroup.getResolvedRule() == null) {
405                 continue;
406             }
407
408             for (ResolvedRule resolvedRule : ruleGroup.getResolvedRule()) {
409                 if (resolvedRule == null) {
410                     continue;
411                 }
412                 if (resolvedRule.getClassifier() == null || resolvedRule.getAction() == null) {
413                     continue;
414                 }
415                 // TODO only first Classifier used
416                 final Classifier classifier = resolvedRule.getClassifier().get(0);
417                 direction = classifier.getDirection();
418                 rulesInDirection.add(resolvedRule);
419             }
420         }
421         if (rulesInDirection.isEmpty()) {
422             return Collections.emptyMap();
423         }
424         // TODO use only first rule with ActionDefinitionID for now
425         final Map<ActionCase, ActionInDirection> result = new HashMap<>();
426         for (ResolvedRule resolvedRule : rulesInDirection) {
427             // TODO only first action used for now
428             final Action action = resolvedRule.getAction().get(0);
429             final RuleName name = resolvedRule.getName();
430             if (action.getActionDefinitionId() != null) {
431                 final ActionDefinitionId actionDefinitionId = action.getActionDefinitionId();
432                 // Currently only chain action is supported
433                 if (actionDefinitionId.equals(ChainActionDefinition.ID)) {
434                     ActionInDirection actionInDirection = new ActionInDirection(name, action, participation, direction);
435                     result.put(ActionCase.CHAIN, actionInDirection);
436                     return result;
437                 }
438             }
439         }
440         return Collections.emptyMap();
441     }
442
443     public static InstanceIdentifier getMountpointIidFromAbsoluteLocation(final RendererEndpoint endpoint,
444                                                                           final List<AddressEndpointWithLocation> endpointsWithLocation) {
445         if (endpointsWithLocation.isEmpty()) {
446             return null;
447         }
448         AddressEndpointWithLocation endpointWithLocation = RendererPolicyUtil.lookupEndpoint(endpoint,
449                 endpointsWithLocation);
450         final AbsoluteLocation absoluteLocation = endpointWithLocation.getAbsoluteLocation();
451         final LocationType locationType = absoluteLocation.getLocationType();
452         ExternalLocationCase location = (ExternalLocationCase) locationType;
453         if (location == null) {
454             LOG.warn("Endpoint {} does not contain info about external location",
455                     endpointWithLocation.getKey().toString());
456             return null;
457         }
458         return location.getExternalNodeMountPoint();
459     }
460
461     public static String getInterfaceNameFromAbsoluteLocation(final RendererEndpoint endpoint,
462                                                               final List<AddressEndpointWithLocation> endpointsWithLocation) {
463         if (endpoint == null || endpointsWithLocation == null) {
464             return null;
465         }
466         final AddressEndpointWithLocation endpointWithLocation = RendererPolicyUtil.lookupEndpoint(endpoint,
467                 endpointsWithLocation);
468         final AbsoluteLocation absoluteLocation = endpointWithLocation.getAbsoluteLocation();
469         final LocationType locationType = absoluteLocation.getLocationType();
470         final ExternalLocationCase location = (ExternalLocationCase) locationType;
471         if (location == null) {
472             LOG.warn("Endpoint {} does not contain info about external location",
473                     endpointWithLocation.getKey().toString());
474             return null;
475         }
476         return location.getExternalNodeConnector();
477     }
478
479     static TenantId getTenantId(final PeerEndpoint peer) {
480         for (RuleGroupWithRendererEndpointParticipation ruleGroup :
481                 peer.getRuleGroupWithRendererEndpointParticipation()) {
482             if (ruleGroup.getTenantId() != null) {
483                 return ruleGroup.getTenantId();
484             }
485         }
486         return null;
487     }
488
489     static String generateClassMapName(final int sourceTag, final int destinationTag) {
490         return "srcTag" + sourceTag + "_dstTag" + destinationTag;
491     }
492
493     public static Optional<Binding> createIpSgtBindingItem(final Sgt sgt, final AddressEndpointWithLocation addressEndpointWithLocation) {
494         final Optional<Binding> result;
495         final LocationType locationType = addressEndpointWithLocation.getAbsoluteLocation().getLocationType();
496
497         if (IpPrefixType.class == addressEndpointWithLocation.getAddressType() &&
498                 locationType instanceof ExternalLocationCase &&
499                 sgt != null) {
500             final Binding binding = new BindingBuilder()
501                     .setSgt(sgt)
502                     .setIpPrefix(new IpPrefix(addressEndpointWithLocation.getAddress().toCharArray()))
503                     .setPeerNode(Collections.singletonList(new PeerNodeBuilder()
504                             .setNodeIid(((ExternalLocationCase) locationType).getExternalNodeMountPoint())
505                             .build()))
506                     .build();
507
508             result = Optional.ofNullable(binding);
509         } else {
510             result = Optional.empty();
511         }
512         return result;
513     }
514
515     /**
516      * Action in Direction - wrapper class
517      */
518     static class ActionInDirection {
519
520         private final RuleName ruleName;
521         private final Action action;
522         private final EndpointPolicyParticipation participation;
523         private final HasDirection.Direction direction;
524
525         ActionInDirection(final RuleName ruleName,
526                           final Action action,
527                           final EndpointPolicyParticipation participation,
528                           final HasDirection.Direction direction) {
529             this.ruleName = Preconditions.checkNotNull(ruleName);
530             this.action = Preconditions.checkNotNull(action);
531             this.participation = Preconditions.checkNotNull(participation);
532             this.direction = Preconditions.checkNotNull(direction);
533         }
534
535         RuleName getRuleName() {
536             return ruleName;
537         }
538
539         Action getAction() {
540             return action;
541         }
542
543         EndpointPolicyParticipation getParticipation() {
544             return participation;
545         }
546
547         HasDirection.Direction getDirection() {
548             return direction;
549         }
550     }
551 }