6fe1d1ebe5e9971ca83c48dd11ebd77e06b2b932
[groupbasedpolicy.git] / neutron-mapper / src / main / java / org / opendaylight / groupbasedpolicy / neutron / mapper / mapping / rule / SecRuleEntityDecoder.java
1 /*
2  * Copyright (c) 2014 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.neutron.mapper.mapping.rule;
10
11 import static com.google.common.base.Preconditions.checkNotNull;
12
13 import com.google.common.collect.ImmutableList;
14
15 import java.util.ArrayList;
16 import java.util.List;
17
18 import org.opendaylight.groupbasedpolicy.api.sf.EtherTypeClassifierDefinition;
19 import org.opendaylight.groupbasedpolicy.api.sf.IpProtoClassifierDefinition;
20 import org.opendaylight.groupbasedpolicy.api.sf.L4ClassifierDefinition;
21 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierName;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.change.action.of.security.group.rules.input.action.ActionChoice;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.change.action.of.security.group.rules.input.action.action.choice.AllowActionCase;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.change.action.of.security.group.rules.input.action.action.choice.SfcActionCase;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.action.refs.ActionRef;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRef;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRef.ConnectionTracking;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRefBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.endpoint.identification.constraints.EndpointIdentificationConstraints;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.endpoint.identification.constraints.EndpointIdentificationConstraintsBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.endpoint.identification.constraints.endpoint.identification.constraints.L3EndpointIdentificationConstraintsBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.endpoint.identification.constraints.endpoint.identification.constraints.l3.endpoint.identification.constraints.PrefixConstraint;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.endpoint.identification.constraints.endpoint.identification.constraints.l3.endpoint.identification.constraints.PrefixConstraintBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValueBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.parameter.value.RangeValueBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.Clause;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.ClauseBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.ConsumerMatchers;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.ConsumerMatchersBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ClassifierInstance;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ClassifierInstanceBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.DirectionBase;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.DirectionEgress;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.DirectionIngress;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.EthertypeBase;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.EthertypeV4;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.EthertypeV6;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolIcmp;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolIcmpV6;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolTcp;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolUdp;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.SecurityRuleAttributes;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.security.rules.SecurityRule;
61
62 public class SecRuleEntityDecoder {
63
64     private SecRuleEntityDecoder() {
65         throw new UnsupportedOperationException("Cannot create an instance.");
66     }
67
68     public static ContractId getContractId(SecurityRule secRule) {
69         return new ContractId(secRule.getUuid().getValue());
70     }
71
72     public static ClassifierInstance getClassifierInstance(SecurityRule secRule) {
73         ClassifierInstanceBuilder classifierBuilder = new ClassifierInstanceBuilder();
74         List<ParameterValue> params = new ArrayList<>();
75         Integer portMin = secRule.getPortRangeMin();
76         Integer portMax = secRule.getPortRangeMax();
77         if (portMin != null && portMax != null) {
78             classifierBuilder.setClassifierDefinitionId(L4ClassifierDefinition.DEFINITION.getId());
79             if (portMin.equals(portMax)) {
80                 params.add(new ParameterValueBuilder().setName(new ParameterName(L4ClassifierDefinition.DST_PORT_PARAM))
81                     .setIntValue(portMin.longValue())
82                     .build());
83             } else {
84                 params.add(new ParameterValueBuilder()
85                     .setName(new ParameterName(L4ClassifierDefinition.DST_PORT_RANGE_PARAM))
86                     .setRangeValue(
87                             new RangeValueBuilder().setMin(portMin.longValue()).setMax(portMax.longValue()).build())
88                     .build());
89             }
90         }
91         Long protocol = getProtocol(secRule);
92         if (protocol != null) {
93             if (classifierBuilder.getClassifierDefinitionId() == null) {
94                 classifierBuilder.setClassifierDefinitionId(IpProtoClassifierDefinition.DEFINITION.getId());
95             }
96             params.add(new ParameterValueBuilder()
97                 .setName(new ParameterName(IpProtoClassifierDefinition.PROTO_PARAM))
98                 .setIntValue(protocol)
99                 .build());
100         }
101         Long ethertype = getEtherType(secRule);
102         if (ethertype != null) {
103             if (classifierBuilder.getClassifierDefinitionId() == null) {
104                 classifierBuilder.setClassifierDefinitionId(EtherTypeClassifierDefinition.DEFINITION.getId());
105             }
106             params.add(new ParameterValueBuilder()
107                 .setName(new ParameterName(EtherTypeClassifierDefinition.ETHERTYPE_PARAM))
108                 .setIntValue(ethertype)
109                 .build());
110         }
111         ClassifierName classifierName = SecRuleNameDecoder.getClassifierInstanceName(secRule);
112         return classifierBuilder.setParameterValue(params).setName(new ClassifierName(classifierName)).build();
113     }
114
115     public static ActionRef createActionRefFromActionChoice(ActionChoice action) {
116         if (action instanceof SfcActionCase) {
117             return MappingUtils.createSfcActionRef(((SfcActionCase) action).getSfcChainName());
118         } else if (action instanceof AllowActionCase) {
119             return MappingUtils.ACTION_REF_ALLOW;
120         }
121         return null;
122     }
123
124     public static ClassifierRef getClassifierRef(SecurityRule secRule) {
125         checkNotNull(secRule);
126         ClassifierName classifierInstanceName = SecRuleNameDecoder.getClassifierInstanceName(secRule);
127         ClassifierRefBuilder classifierRefBuilder = new ClassifierRefBuilder()
128             .setConnectionTracking(ConnectionTracking.Reflexive).setInstanceName(classifierInstanceName);
129         Direction direction = getDirection(secRule);
130         classifierRefBuilder.setDirection(direction);
131         ClassifierName classifierRefName = SecRuleNameDecoder.getClassifierRefName(secRule);
132         return classifierRefBuilder.setName(classifierRefName).build();
133     }
134
135     /**
136      * Resolves Direction for provided secRule.
137      *
138      * @param secRule rule for which Direction is resolved.
139      * @return direction resolved from {@link SecurityRule#getDirection()}
140      * @throws IllegalArgumentException if return value of
141      *         {@link SecurityRule#getDirection()} is other than {@link DirectionIngress} or
142      *         {@link DirectionEgress}
143      */
144     public static Direction getDirection(SecurityRule secRule) {
145         Class<? extends DirectionBase> direction = secRule.getDirection();
146         if (direction == null) {
147             throw new IllegalArgumentException("Direction cannot be null.");
148         }
149         if (direction.isAssignableFrom(DirectionIngress.class)) {
150             return Direction.In;
151         }
152         if (direction.isAssignableFrom(DirectionEgress.class)) {
153             return Direction.Out;
154         }
155         throw new IllegalArgumentException("Direction " + direction + " from security group rule "
156                 + secRule + " is not supported. Direction can be only 'ingress' or 'egress'.");
157     }
158
159     /**
160      * Resolves Clause for provided secRule.
161      *
162      * @param secRule {@link SecurityRule#getRemoteIpPrefix()} is used for EIC
163      *        and subject selection
164      * @return clause with the subject and with a consumer matcher containing EIC
165      */
166     public static Clause getClause(SecurityRule secRule) {
167         checkNotNull(secRule);
168         SubjectName subjectName = SecRuleNameDecoder.getSubjectName(secRule);
169         ClauseBuilder clauseBuilder = new ClauseBuilder()
170             .setSubjectRefs(ImmutableList.of(subjectName))
171             .setName(SecRuleNameDecoder
172                 .getClauseName(secRule));
173         IpPrefix remoteIpPrefix = secRule.getRemoteIpPrefix();
174         if (remoteIpPrefix != null) {
175             clauseBuilder.setConsumerMatchers(createConsumerMatchersWithEic(remoteIpPrefix));
176         }
177         return clauseBuilder.build();
178     }
179
180     private static ConsumerMatchers createConsumerMatchersWithEic(IpPrefix ipPrefix) {
181         PrefixConstraint consumerPrefixConstraint = new PrefixConstraintBuilder().setIpPrefix(ipPrefix).build();
182         EndpointIdentificationConstraints eic =
183                 new EndpointIdentificationConstraintsBuilder()
184                     .setL3EndpointIdentificationConstraints(new L3EndpointIdentificationConstraintsBuilder()
185                         .setPrefixConstraint(ImmutableList.<PrefixConstraint>of(consumerPrefixConstraint)).build())
186                     .build();
187         return new ConsumerMatchersBuilder().setEndpointIdentificationConstraints(eic).build();
188     }
189
190     public static boolean isEtherTypeOfOneWithinTwo(SecurityRule one, SecurityRule two) {
191         Long oneEtherType = getEtherType(one);
192         Long twoEtherType = getEtherType(two);
193         return twoIsNullOrEqualsOne(oneEtherType, twoEtherType);
194     }
195
196     public static boolean isProtocolOfOneWithinTwo(SecurityRule one, SecurityRule two) {
197         Long oneProtocol = getProtocol(one);
198         Long twoProtocol = getProtocol(two);
199         return twoIsNullOrEqualsOne(oneProtocol, twoProtocol);
200     }
201
202     private static <T> boolean twoIsNullOrEqualsOne(T one, T two) {
203         if (two == null) {
204             return true;
205         }
206         if (two.equals(one)) {
207             return true;
208         }
209         return false;
210     }
211
212     public static boolean isPortsOfOneWithinTwo(SecurityRule one, SecurityRule two) {
213         Integer onePortMin = one.getPortRangeMin();
214         Integer onePortMax = one.getPortRangeMax();
215         Integer twoPortMin = two.getPortRangeMin();
216         Integer twoPortMax = two.getPortRangeMax();
217         if (twoPortMin == null && twoPortMax == null) {
218             return true;
219         }
220         if ((onePortMin != null && twoPortMin != null && onePortMin >= twoPortMin)
221                 && (onePortMax != null && twoPortMax != null && onePortMax <= twoPortMax)) {
222             return true;
223         }
224         return false;
225     }
226
227     /**
228      * Resolves EtherType for provided secRule.
229      *
230      * @param secRule rule for which EtherType is resolved.
231      * @return {@code null} if {@link SecurityRule#getEthertype()} is null; Otherwise ethertype
232      *         number
233      * @throws IllegalArgumentException if return value of
234      *         {@link SecurityRule#getEthertype()} is other {@link EthertypeV4} or
235      *         {@link EthertypeV6}
236      */
237     public static Long getEtherType(SecurityRule secRule) {
238         Class<? extends EthertypeBase> ethertype = secRule.getEthertype();
239         if (ethertype == null) {
240             return null;
241         }
242         if (ethertype.isAssignableFrom(EthertypeV4.class)) {
243             return EtherTypeClassifierDefinition.IPv4_VALUE;
244         }
245         if (ethertype.isAssignableFrom(EthertypeV6.class)) {
246             return EtherTypeClassifierDefinition.IPv6_VALUE;
247         }
248         throw new IllegalArgumentException("Ethertype " + ethertype + " is not supported.");
249     }
250
251     /**
252      * Resolves Protocol for provided secRule.
253      *
254      * @param secRule rule for which Protocol is resolved.
255      * @return {@code null} if {@link SecurityRule#getProtocol()} is null; Otherwise protocol number
256      * @throws IllegalArgumentException if return value of
257      *         {@link SecurityRule#getProtocol()} is other than {@link ProtocolTcp},
258      *         {@link ProtocolUdp}, {@link ProtocolIcmp}, {@link ProtocolIcmpV6}
259      */
260     public static Long getProtocol(SecurityRule secRule) {
261         SecurityRuleAttributes.Protocol protocol = secRule.getProtocol();
262         if (protocol == null) {
263             return null;
264         }
265         if (protocol.getUint8() != null) {
266             return protocol.getUint8().longValue();
267         }
268         if (protocol.getIdentityref() != null) {
269             if (protocol.getIdentityref().equals(ProtocolTcp.class)) {
270                 return IpProtoClassifierDefinition.TCP_VALUE;
271             }
272             if (protocol.getIdentityref().equals(ProtocolUdp.class)) {
273                 return IpProtoClassifierDefinition.UDP_VALUE;
274             }
275             if (protocol.getIdentityref().equals(ProtocolIcmp.class)) {
276                 return IpProtoClassifierDefinition.ICMP_VALUE;
277             }
278             if (protocol.getIdentityref().equals(ProtocolIcmpV6.class)) {
279                 return IpProtoClassifierDefinition.ICMPv6_VALUE;
280             }
281         }
282         throw new IllegalArgumentException("Neutron Security Rule Protocol value " + protocol + " is not supported.");
283     }
284 }