Bug 5409 - setting orders in single rule contract
[groupbasedpolicy.git] / neutron-mapper / src / main / java / org / opendaylight / groupbasedpolicy / neutron / mapper / mapping / rule / SecRuleEntityDecoder.java
1 /*\r
2  * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.\r
3  *\r
4  * This program and the accompanying materials are made available under the\r
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
6  * and is available at http://www.eclipse.org/legal/epl-v10.html\r
7  */\r
8 \r
9 package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.rule;\r
10 \r
11 import static com.google.common.base.Preconditions.checkNotNull;\r
12 \r
13 import java.util.ArrayList;\r
14 import java.util.List;\r
15 \r
16 import javax.annotation.Nullable;\r
17 \r
18 import org.opendaylight.groupbasedpolicy.api.sf.EtherTypeClassifierDefinition;\r
19 import org.opendaylight.groupbasedpolicy.api.sf.IpProtoClassifierDefinition;\r
20 import org.opendaylight.groupbasedpolicy.api.sf.L4ClassifierDefinition;\r
21 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;\r
22 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.NeutronUtils;\r
23 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.Utils;\r
24 import org.opendaylight.neutron.spi.NeutronSecurityRule;\r
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;\r
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierName;\r
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;\r
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;\r
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;\r
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;\r
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;\r
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.change.action.of.security.group.rules.input.action.ActionChoice;\r
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.change.action.of.security.group.rules.input.action.action.choice.AllowActionCase;\r
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.change.action.of.security.group.rules.input.action.action.choice.SfcActionCase;\r
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction;\r
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.action.refs.ActionRef;\r
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRef;\r
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRef.ConnectionTracking;\r
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRefBuilder;\r
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.endpoint.identification.constraints.EndpointIdentificationConstraints;\r
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.endpoint.identification.constraints.EndpointIdentificationConstraintsBuilder;\r
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.endpoint.identification.constraints.endpoint.identification.constraints.L3EndpointIdentificationConstraintsBuilder;\r
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.endpoint.identification.constraints.endpoint.identification.constraints.l3.endpoint.identification.constraints.PrefixConstraint;\r
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.endpoint.identification.constraints.endpoint.identification.constraints.l3.endpoint.identification.constraints.PrefixConstraintBuilder;\r
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue;\r
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValueBuilder;\r
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.parameter.value.RangeValueBuilder;\r
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.Clause;\r
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.ClauseBuilder;\r
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.ConsumerMatchers;\r
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.ConsumerMatchersBuilder;\r
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ClassifierInstance;\r
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ClassifierInstanceBuilder;\r
54 \r
55 import com.google.common.base.Strings;\r
56 import com.google.common.collect.ImmutableList;\r
57 \r
58 public class SecRuleEntityDecoder {\r
59 \r
60     private SecRuleEntityDecoder() {\r
61         throw new UnsupportedOperationException("Cannot create an instace.");\r
62     }\r
63 \r
64     public static TenantId getTenantId(NeutronSecurityRule secRule) {\r
65         return new TenantId(Utils.normalizeUuid(secRule.getSecurityRuleTenantID()));\r
66     }\r
67 \r
68     public static EndpointGroupId getProviderEpgId(NeutronSecurityRule secRule) {\r
69         return new EndpointGroupId(Utils.normalizeUuid(secRule.getSecurityRuleGroupID()));\r
70     }\r
71 \r
72     public static @Nullable EndpointGroupId getConsumerEpgId(NeutronSecurityRule secRule) {\r
73         if (Strings.isNullOrEmpty(secRule.getSecurityRemoteGroupID())) {\r
74             return null;\r
75         }\r
76         return new EndpointGroupId(Utils.normalizeUuid(secRule.getSecurityRemoteGroupID()));\r
77     }\r
78 \r
79     public static ContractId getContractId(NeutronSecurityRule secRule) {\r
80         return new ContractId(Utils.normalizeUuid(secRule.getSecurityRuleUUID()));\r
81     }\r
82 \r
83     public static ClassifierInstance getClassifierInstance(NeutronSecurityRule secRule) {\r
84         ClassifierInstanceBuilder classifierBuilder = new ClassifierInstanceBuilder();\r
85         List<ParameterValue> params = new ArrayList<>();\r
86         Integer portMin = secRule.getSecurityRulePortMin();\r
87         Integer portMax = secRule.getSecurityRulePortMax();\r
88         if (portMin != null && portMax != null) {\r
89             classifierBuilder.setClassifierDefinitionId(L4ClassifierDefinition.DEFINITION.getId());\r
90             if (portMin.equals(portMax)) {\r
91                 params.add(new ParameterValueBuilder().setName(new ParameterName(L4ClassifierDefinition.DST_PORT_PARAM))\r
92                     .setIntValue(portMin.longValue())\r
93                     .build());\r
94             } else {\r
95                 params.add(new ParameterValueBuilder().setName(new ParameterName(L4ClassifierDefinition.DST_PORT_RANGE_PARAM))\r
96                     .setRangeValue(\r
97                             new RangeValueBuilder().setMin(portMin.longValue()).setMax(portMax.longValue()).build())\r
98                     .build());\r
99             }\r
100         }\r
101         Long protocol = getProtocol(secRule);\r
102         if (protocol != null) {\r
103             if (classifierBuilder.getClassifierDefinitionId() == null) {\r
104                 classifierBuilder.setClassifierDefinitionId(IpProtoClassifierDefinition.DEFINITION.getId());\r
105             }\r
106             params.add(new ParameterValueBuilder().setName(new ParameterName(IpProtoClassifierDefinition.PROTO_PARAM))\r
107                 .setIntValue(protocol)\r
108                 .build());\r
109         }\r
110         Long ethertype = getEtherType(secRule);\r
111         if (ethertype != null) {\r
112             if (classifierBuilder.getClassifierDefinitionId() == null) {\r
113                 classifierBuilder.setClassifierDefinitionId(EtherTypeClassifierDefinition.DEFINITION.getId());\r
114             }\r
115             params.add(new ParameterValueBuilder().setName(new ParameterName(EtherTypeClassifierDefinition.ETHERTYPE_PARAM))\r
116                 .setIntValue(ethertype)\r
117                 .build());\r
118         }\r
119         ClassifierName classifierName = SecRuleNameDecoder.getClassifierInstanceName(secRule);\r
120         return classifierBuilder.setParameterValue(params).setName(new ClassifierName(classifierName)).build();\r
121     }\r
122 \r
123     public static ActionRef createActionRefFromActionChoice(ActionChoice action) {\r
124         if(action instanceof SfcActionCase){\r
125             return MappingUtils.createSfcActionRef(((SfcActionCase) action).getSfcChainName());\r
126         } else if (action instanceof AllowActionCase) {\r
127             return MappingUtils.ACTION_REF_ALLOW;\r
128         }\r
129         return null;\r
130     }\r
131 \r
132     public static ClassifierRef getClassifierRef(NeutronSecurityRule secRule) {\r
133         checkNotNull(secRule);\r
134         ClassifierName classifierInstanceName = SecRuleNameDecoder.getClassifierInstanceName(secRule);\r
135         ClassifierRefBuilder classifierRefBuilder = new ClassifierRefBuilder()\r
136             .setConnectionTracking(ConnectionTracking.Reflexive).setInstanceName(classifierInstanceName);\r
137         Direction direction = getDirection(secRule);\r
138         classifierRefBuilder.setDirection(direction);\r
139         ClassifierName classifierRefName = SecRuleNameDecoder.getClassifierRefName(secRule);\r
140         return classifierRefBuilder.setName(classifierRefName).build();\r
141     }\r
142 \r
143     /**\r
144      * @param secRule\r
145      * @return direction resolved from {@link NeutronSecurityRule#getSecurityRuleDirection()}\r
146      * @throws IllegalArgumentException if return value of\r
147      *         {@link NeutronSecurityRule#getSecurityRuleDirection()} is other than "ingress" or\r
148      *         "egress"\r
149      */\r
150     public static Direction getDirection(NeutronSecurityRule secRule) {\r
151         String direction = secRule.getSecurityRuleDirection();\r
152         if (NeutronUtils.INGRESS.equals(direction)) {\r
153             return Direction.In;\r
154         }\r
155         if (NeutronUtils.EGRESS.equals(direction)) {\r
156             return Direction.Out;\r
157         }\r
158         throw new IllegalArgumentException("Direction " + direction + " from security group rule "\r
159                 + secRule.getSecurityRuleUUID() + " is not supported. Direction can be only 'ingress' or 'egress'.");\r
160     }\r
161 \r
162     /**\r
163      * @param secRule {@link NeutronSecurityRule#getSecurityRuleRemoteIpPrefix()} is used for EIC\r
164      *        and subject selection\r
165      * @return clause with the subject and with a consumer matcher containing EIC\r
166      */\r
167     public static Clause getClause(NeutronSecurityRule secRule) {\r
168         checkNotNull(secRule);\r
169         SubjectName subjectName = SecRuleNameDecoder.getSubjectName(secRule);\r
170         ClauseBuilder clauseBuilder =\r
171                 new ClauseBuilder().setSubjectRefs(ImmutableList.of(subjectName)).setName(SecRuleNameDecoder.getClauseName(secRule));\r
172         String remoteIpPrefix = secRule.getSecurityRuleRemoteIpPrefix();\r
173         if (!Strings.isNullOrEmpty(remoteIpPrefix)) {\r
174             clauseBuilder.setConsumerMatchers(createConsumerMatchersWithEic(remoteIpPrefix));\r
175         }\r
176         return clauseBuilder.build();\r
177     }\r
178 \r
179     private static ConsumerMatchers createConsumerMatchersWithEic(String remoteIpPrefix) {\r
180         IpPrefix ipPrefix = Utils.createIpPrefix(remoteIpPrefix);\r
181         PrefixConstraint consumerPrefixConstraint = new PrefixConstraintBuilder().setIpPrefix(ipPrefix).build();\r
182         EndpointIdentificationConstraints eic =\r
183                 new EndpointIdentificationConstraintsBuilder()\r
184                     .setL3EndpointIdentificationConstraints(new L3EndpointIdentificationConstraintsBuilder()\r
185                         .setPrefixConstraint(ImmutableList.<PrefixConstraint>of(consumerPrefixConstraint)).build())\r
186                     .build();\r
187         return new ConsumerMatchersBuilder().setEndpointIdentificationConstraints(eic).build();\r
188     }\r
189 \r
190     public static boolean isEtherTypeOfOneWithinTwo(NeutronSecurityRule one, NeutronSecurityRule two) {\r
191         Long oneEtherType = getEtherType(one);\r
192         Long twoEtherType = getEtherType(two);\r
193         return twoIsNullOrEqualsOne(oneEtherType, twoEtherType);\r
194     }\r
195 \r
196     public static boolean isProtocolOfOneWithinTwo(NeutronSecurityRule one, NeutronSecurityRule two) {\r
197         Long oneProtocol = getProtocol(one);\r
198         Long twoProtocol = getProtocol(two);\r
199         return twoIsNullOrEqualsOne(oneProtocol, twoProtocol);\r
200     }\r
201 \r
202     private static <T> boolean twoIsNullOrEqualsOne(T one, T two) {\r
203         if (two == null)\r
204             return true;\r
205         if (two.equals(one))\r
206             return true;\r
207         return false;\r
208     }\r
209 \r
210     public static boolean isPortsOfOneWithinTwo(NeutronSecurityRule one, NeutronSecurityRule two) {\r
211         Integer onePortMin = one.getSecurityRulePortMin();\r
212         Integer onePortMax = one.getSecurityRulePortMax();\r
213         Integer twoPortMin = two.getSecurityRulePortMin();\r
214         Integer twoPortMax = two.getSecurityRulePortMax();\r
215         if (twoPortMin == null && twoPortMax == null) {\r
216             return true;\r
217         }\r
218         if ((onePortMin != null && twoPortMin != null && onePortMin >= twoPortMin)\r
219                 && (onePortMax != null && twoPortMax != null && onePortMax <= twoPortMax)) {\r
220             return true;\r
221         }\r
222         return false;\r
223     }\r
224 \r
225     /**\r
226      * @param secRule\r
227      * @return {@code null} if {@link NeutronSecurityRule#getSecurityRuleEthertype()} is null or\r
228      *         empty; value of {@link EtherTypeClassifierDefinition#IPv4_VALUE} or\r
229      *         {@link EtherTypeClassifierDefinition#IPv6_VALUE}\r
230      * @throws IllegalArgumentException if return value of\r
231      *         {@link NeutronSecurityRule#getSecurityRuleEthertype()} is not empty/null and is other\r
232      *         than "IPv4" or "IPv6"\r
233      */\r
234     public static Long getEtherType(NeutronSecurityRule secRule) {\r
235         String ethertype = secRule.getSecurityRuleEthertype();\r
236         if (Strings.isNullOrEmpty(ethertype)) {\r
237             return null;\r
238         }\r
239         if (NeutronUtils.IPv4.equals(ethertype)) {\r
240             return EtherTypeClassifierDefinition.IPv4_VALUE;\r
241         }\r
242         if (NeutronUtils.IPv6.equals(ethertype)) {\r
243             return EtherTypeClassifierDefinition.IPv6_VALUE;\r
244         }\r
245         throw new IllegalArgumentException("Ethertype " + ethertype + " is not supported.");\r
246     }\r
247 \r
248     /**\r
249      * @param secRule\r
250      * @return {@code null} if {@link NeutronSecurityRule#getSecurityRuleProtocol()} is null or\r
251      *         empty; Otherwise protocol number\r
252      * @throws IllegalArgumentException if return value of\r
253      *         {@link NeutronSecurityRule#getSecurityRuleProtocol()} is not empty/null and is other\r
254      *         than "tcp", "udp", "icmp", "icmpv6" or string values that can be decoded to {@link Short}.\r
255      */\r
256     public static Long getProtocol(NeutronSecurityRule secRule) {\r
257         String protocol = secRule.getSecurityRuleProtocol();\r
258         if (Strings.isNullOrEmpty(protocol)) {\r
259             return null;\r
260         }\r
261         if (NeutronUtils.TCP.equals(protocol)) {\r
262             return IpProtoClassifierDefinition.TCP_VALUE;\r
263         }\r
264         if (NeutronUtils.UDP.equals(protocol)) {\r
265             return IpProtoClassifierDefinition.UDP_VALUE;\r
266         }\r
267         if (NeutronUtils.ICMP.equals(protocol)) {\r
268             return IpProtoClassifierDefinition.ICMP_VALUE;\r
269         }\r
270         if (NeutronUtils.ICMPv6.equals(protocol)) {\r
271             return IpProtoClassifierDefinition.ICMPv6_VALUE;\r
272         }\r
273         Long protocolNum;\r
274         try {\r
275             protocolNum = Long.valueOf(protocol);\r
276         } catch (NumberFormatException e) {\r
277             throw new IllegalArgumentException("Neutron Security Rule Protocol value " + protocol\r
278                     + " is not supported.");\r
279         }\r
280         return protocolNum;\r
281     }\r
282 }\r