Introduced neutron-mapper
[groupbasedpolicy.git] / neutron-mapper / src / main / java / org / opendaylight / groupbasedpolicy / neutron / mapper / mapping / TransformSecRule.java
1 package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping;
2
3 import static com.google.common.base.Preconditions.checkNotNull;
4
5 import java.util.ArrayList;
6 import java.util.List;
7
8 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
9 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.NeutronUtils;
10 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.Utils;
11 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.EtherTypeClassifier;
12 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.IpProtoClassifier;
13 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.L4Classifier;
14 import org.opendaylight.neutron.spi.NeutronSecurityRule;
15 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierName;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClauseName;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.RuleName;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.action.refs.ActionRef;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.action.refs.ActionRefBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRef;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRef.ConnectionTracking;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRefBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValueBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.parameter.value.RangeValueBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Clause;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.ClauseBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Subject;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.SubjectBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.ConsumerMatchersBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.ProviderMatchersBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.consumer.matchers.EndpointIdentificationConstraintsBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.consumer.matchers.endpoint.identification.constraints.L3EndpointIdentificationConstraintsBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.consumer.matchers.endpoint.identification.constraints.l3.endpoint.identification.constraints.PrefixConstraint;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.consumer.matchers.endpoint.identification.constraints.l3.endpoint.identification.constraints.PrefixConstraintBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.subject.Rule;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.subject.RuleBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ClassifierInstance;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ClassifierInstanceBuilder;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48
49 import com.google.common.base.Strings;
50 import com.google.common.collect.ImmutableList;
51
52 public class TransformSecRule {
53
54     private static final Logger LOG = LoggerFactory.getLogger(TransformSecRule.class);
55     private static final List<ActionRef> ACTION_REF_ALLOW = ImmutableList.of(new ActionRefBuilder().setName(
56             MappingUtils.ACTION_ALLOW.getName())
57         .setOrder(0)
58         .build());
59     private final NeutronSecurityRule secRule;
60     private final TenantId tenantId;
61     private final EndpointGroupId providerEpgId;
62     private final EndpointGroupId consumerEpgId;
63     private final SubjectName subjectName;
64     private final ClauseName clauseName;
65     private final IpPrefix ipPrefix;
66     private final int subjectOrder;
67     private final ClassifierName classifierName;
68     private final RuleName ruleName;
69
70     /**
71      * If a {@link NeutronSecurityRule#getSecurityRuleGroupID()} is {@link MappingUtils#EPG_DHCP_ID}
72      * or {@link MappingUtils#EPG_ROUTER_ID} then the neutron security rule can contain remote ip
73      * prefix besides remote ip security group. I this case {@link #getConsumerEpgId()} returns remote security group id.
74      *
75      * @param secRule
76      */
77     public TransformSecRule(NeutronSecurityRule secRule) {
78         this.secRule = checkNotNull(secRule);
79         tenantId = new TenantId(Utils.normalizeUuid(secRule.getSecurityRuleTenantID()));
80         providerEpgId = new EndpointGroupId(secRule.getSecurityRuleGroupID());
81         if (!Strings.isNullOrEmpty(secRule.getSecurityRemoteGroupID())) {
82             consumerEpgId = new EndpointGroupId(secRule.getSecurityRemoteGroupID());
83             if (isEpgIdRouterOrDhcp(providerEpgId) && !Strings.isNullOrEmpty(secRule.getSecurityRuleRemoteIpPrefix())) {
84                 ipPrefix = Utils.createIpPrefix(secRule.getSecurityRuleRemoteIpPrefix());
85             } else {
86                 ipPrefix = null;
87             }
88             subjectOrder = 0;
89         } else if (!Strings.isNullOrEmpty(secRule.getSecurityRuleRemoteIpPrefix())) {
90             consumerEpgId = MappingUtils.EPG_ANY_ID;
91             ipPrefix = Utils.createIpPrefix(secRule.getSecurityRuleRemoteIpPrefix());
92             subjectOrder = 0;
93         } else {
94             consumerEpgId = MappingUtils.EPG_ANY_ID;
95             ipPrefix = null;
96             subjectOrder = 1;
97         }
98         subjectName = createSubjectName();
99         clauseName = new ClauseName(subjectName.getValue());
100         classifierName = new ClassifierName(MappingUtils.NEUTRON_RULE__ + secRule.getSecurityRuleUUID());
101         ruleName = new RuleName(MappingUtils.NEUTRON_RULE__ + "Allow--" + classifierName.getValue());
102     }
103
104     private SubjectName createSubjectName() {
105         if (ipPrefix == null) {
106             return new SubjectName(MappingUtils.NEUTRON_RULE__ + providerEpgId.getValue() + "__"
107                     + consumerEpgId.getValue());
108         }
109         String prefix = Utils.getStringIpPrefix(ipPrefix).replace('/', '_');
110         return new SubjectName(MappingUtils.NEUTRON_RULE__ + providerEpgId.getValue() + "__" + prefix + "__"
111                 + consumerEpgId.getValue());
112     }
113
114     public Clause createClause() {
115         ClauseBuilder clauseBuilder = new ClauseBuilder().setName(clauseName).setSubjectRefs(
116                 ImmutableList.of(subjectName));
117         if (ipPrefix != null) {
118             clauseBuilder.setConsumerMatchers(new ConsumerMatchersBuilder().setEndpointIdentificationConstraints(
119                     new EndpointIdentificationConstraintsBuilder().setL3EndpointIdentificationConstraints(
120                             new L3EndpointIdentificationConstraintsBuilder().setPrefixConstraint(
121                                     ImmutableList.<PrefixConstraint>of(new PrefixConstraintBuilder().setIpPrefix(
122                                             ipPrefix).build())).build()).build()).build());
123             if (isEpgIdRouterOrDhcp(providerEpgId)) {
124                 clauseBuilder.setProviderMatchers(new ProviderMatchersBuilder().setEndpointIdentificationConstraints(
125                         new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.provider.matchers.EndpointIdentificationConstraintsBuilder().setL3EndpointIdentificationConstraints(
126                                 new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.provider.matchers.endpoint.identification.constraints.L3EndpointIdentificationConstraintsBuilder().setPrefixConstraint(
127                                         ImmutableList.<org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.provider.matchers.endpoint.identification.constraints.l3.endpoint.identification.constraints.PrefixConstraint>of(new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.provider.matchers.endpoint.identification.constraints.l3.endpoint.identification.constraints.PrefixConstraintBuilder().setIpPrefix(
128                                                 ipPrefix)
129                                             .build()))
130                                     .build())
131                             .build())
132                     .build());
133             }
134         }
135         return clauseBuilder.build();
136     }
137
138     private static boolean isEpgIdRouterOrDhcp(EndpointGroupId epgId) {
139         return (MappingUtils.EPG_ROUTER_ID.equals(epgId) || MappingUtils.EPG_DHCP_ID.equals(epgId));
140     }
141
142     public ClassifierInstance createClassifier() {
143         ClassifierInstanceBuilder classifierBuilder = new ClassifierInstanceBuilder().setName(classifierName);
144         List<ParameterValue> params = new ArrayList<>();
145         Integer portMin = secRule.getSecurityRulePortMin();
146         Integer portMax = secRule.getSecurityRulePortMax();
147         if (portMin != null && portMax != null) {
148             classifierBuilder.setClassifierDefinitionId(L4Classifier.DEFINITION.getId());
149             if (portMin.equals(portMax)) {
150                 params.add(new ParameterValueBuilder().setName(new ParameterName(L4Classifier.DST_PORT_PARAM))
151                     .setIntValue(portMin.longValue())
152                     .build());
153             } else {
154                 params.add(new ParameterValueBuilder().setName(new ParameterName(L4Classifier.DST_PORT_RANGE_PARAM))
155                     .setRangeValue(
156                             new RangeValueBuilder().setMin(portMin.longValue()).setMax(portMax.longValue()).build())
157                     .build());
158             }
159         }
160         String protocol = secRule.getSecurityRuleProtocol();
161         if (!Strings.isNullOrEmpty(protocol)) {
162             if (classifierBuilder.getClassifierDefinitionId() == null) {
163                 classifierBuilder.setClassifierDefinitionId(IpProtoClassifier.DEFINITION.getId());
164             }
165             if (NeutronUtils.TCP.equals(protocol)) {
166                 params.add(new ParameterValueBuilder().setName(new ParameterName(IpProtoClassifier.PROTO_PARAM))
167                     .setIntValue(IpProtoClassifier.TCP_VALUE)
168                     .build());
169             } else if (NeutronUtils.UDP.equals(protocol)) {
170                 params.add(new ParameterValueBuilder().setName(new ParameterName(IpProtoClassifier.PROTO_PARAM))
171                     .setIntValue(IpProtoClassifier.UDP_VALUE)
172                     .build());
173             } else if (NeutronUtils.ICMP.equals(protocol)) {
174                 params.add(new ParameterValueBuilder().setName(new ParameterName(IpProtoClassifier.PROTO_PARAM))
175                     .setIntValue(1L)
176                     .build());
177             } else if (NeutronUtils.NULL.equals(protocol)) {
178                 LOG.debug("Protocol is not specified in security group rule {}", secRule.getSecurityRuleUUID());
179             } else {
180                 throw new IllegalArgumentException("Protocol " + protocol + " is not supported.");
181             }
182         }
183         String ethertype = secRule.getSecurityRuleEthertype();
184         if (!Strings.isNullOrEmpty(ethertype)) {
185             if (classifierBuilder.getClassifierDefinitionId() == null) {
186                 classifierBuilder.setClassifierDefinitionId(EtherTypeClassifier.DEFINITION.getId());
187             }
188             if (NeutronUtils.IPv4.equals(ethertype)) {
189                 params.add(new ParameterValueBuilder().setName(new ParameterName(EtherTypeClassifier.ETHERTYPE_PARAM))
190                     .setIntValue(EtherTypeClassifier.IPv4_VALUE)
191                     .build());
192             } else if (NeutronUtils.IPv6.equals(ethertype)) {
193                 params.add(new ParameterValueBuilder().setName(new ParameterName(EtherTypeClassifier.ETHERTYPE_PARAM))
194                     .setIntValue(EtherTypeClassifier.IPv6_VALUE)
195                     .build());
196             } else {
197                 throw new IllegalArgumentException("Ethertype " + ethertype + " is not supported.");
198             }
199         }
200         return classifierBuilder.setParameterValue(params).build();
201     }
202
203     public Rule createRule(int order) {
204         return new RuleBuilder().setName(ruleName)
205             .setOrder(order)
206             .setActionRef(ACTION_REF_ALLOW)
207             .setClassifierRef(ImmutableList.of(createClassifierRef()))
208             .build();
209     }
210
211     public Subject createSubject() {
212         return new SubjectBuilder().setName(subjectName).setOrder(subjectOrder).build();
213     }
214
215     private ClassifierRef createClassifierRef() {
216         ClassifierRefBuilder classifierRefBuilder = new ClassifierRefBuilder().setName(classifierName)
217             .setConnectionTracking(ConnectionTracking.Reflexive)
218             .setInstanceName(classifierName);
219         String direction = secRule.getSecurityRuleDirection();
220         if (NeutronUtils.INGRESS.equals(direction)) {
221             classifierRefBuilder.setDirection(Direction.In);
222         } else if (NeutronUtils.EGRESS.equals(direction)) {
223             classifierRefBuilder.setDirection(Direction.Out);
224         } else {
225             throw new IllegalArgumentException("Direction " + direction + " from security group rule "
226                     + secRule.getSecurityRuleUUID() + " is not supported. Direction can be only 'ingress' or 'egress'.");
227         }
228         return classifierRefBuilder.build();
229     }
230
231     public TenantId getTenantId() {
232         return tenantId;
233     }
234
235     public EndpointGroupId getProviderEpgId() {
236         return providerEpgId;
237     }
238
239     public EndpointGroupId getConsumerEpgId() {
240         return consumerEpgId;
241     }
242
243     public SubjectName getSubjectName() {
244         return subjectName;
245     }
246
247     public ClauseName getClauseName() {
248         return clauseName;
249     }
250
251     public IpPrefix getIpPrefix() {
252         return ipPrefix;
253     }
254
255     public ClassifierName getClassifierName() {
256         return classifierName;
257     }
258
259     public RuleName getRuleName() {
260         return ruleName;
261     }
262
263 }