2 * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. 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
8 package org.opendaylight.netvirt.neutronvpn;
10 import com.google.common.collect.ImmutableBiMap;
11 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
12 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
13 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
14 import org.opendaylight.genius.mdsalutil.MDSALUtil;
15 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.AccessLists;
16 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
17 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclKey;
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.AccessListEntries;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.AceBuilder;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.AceKey;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.ActionsBuilder;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.MatchesBuilder;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.actions.packet.handling.PermitBuilder;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIpBuilder;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv4Builder;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv6Builder;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160218.acl.transport.header.fields.DestinationPortRangeBuilder;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160218.acl.transport.header.fields.SourcePortRangeBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttr;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttrBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.DirectionBase;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.DirectionEgress;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.DirectionIngress;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolBase;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolIcmp;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolIcmpV6;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolTcp;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolUdp;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.SecurityRuleAttributes;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.SecurityRules;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.security.rules.SecurityRule;
47 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
51 public class NeutronSecurityRuleListener
52 extends AsyncDataTreeChangeListenerBase<SecurityRule, NeutronSecurityRuleListener> {
53 private static final Logger LOG = LoggerFactory.getLogger(NeutronSecurityRuleListener.class);
54 private final DataBroker dataBroker;
55 private static final ImmutableBiMap<Class<? extends DirectionBase>,
56 Class<?extends org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionBase>>
57 DIRECTION_MAP = ImmutableBiMap.of(
58 DirectionEgress.class, NeutronSecurityRuleConstants.DIRECTION_EGRESS,
59 DirectionIngress.class, NeutronSecurityRuleConstants.DIRECTION_INGRESS);
60 private static final ImmutableBiMap<Class<? extends ProtocolBase>, Short> PROTOCOL_MAP = ImmutableBiMap.of(
61 ProtocolIcmp.class, NeutronSecurityRuleConstants.PROTOCOL_ICMP,
62 ProtocolTcp.class, NeutronSecurityRuleConstants.PROTOCOL_TCP,
63 ProtocolUdp.class, NeutronSecurityRuleConstants.PROTOCOL_UDP,
64 ProtocolIcmpV6.class, NeutronSecurityRuleConstants.PROTOCOL_ICMPV6);
66 public NeutronSecurityRuleListener(final DataBroker dataBroker) {
67 super(SecurityRule.class, NeutronSecurityRuleListener.class);
68 this.dataBroker = dataBroker;
72 LOG.info("{} start", getClass().getSimpleName());
73 registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
77 protected InstanceIdentifier<SecurityRule> getWildCardPath() {
78 return InstanceIdentifier.create(Neutron.class).child(SecurityRules.class).child(SecurityRule.class);
82 // TODO Clean up the exception handling
83 @SuppressWarnings("checkstyle:IllegalCatch")
84 protected void add(InstanceIdentifier<SecurityRule> instanceIdentifier, SecurityRule securityRule) {
85 LOG.trace("added securityRule: {}", securityRule);
87 Ace ace = toAceBuilder(securityRule).build();
88 InstanceIdentifier<Ace> identifier = getAceInstanceIdentifier(securityRule);
89 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, identifier, ace);
90 } catch (Exception ex) {
91 LOG.error("Exception occured while adding acl for security rule: ", ex);
95 private InstanceIdentifier<Ace> getAceInstanceIdentifier(SecurityRule securityRule) {
96 return InstanceIdentifier
97 .builder(AccessLists.class)
99 new AclKey(securityRule.getSecurityGroupId().getValue(), NeutronSecurityRuleConstants.ACLTYPE))
100 .child(AccessListEntries.class)
102 new AceKey(securityRule.getUuid().getValue()))
106 private AceBuilder toAceBuilder(SecurityRule securityRule) {
107 AceIpBuilder aceIpBuilder = new AceIpBuilder();
108 SecurityRuleAttrBuilder securityRuleAttrBuilder = new SecurityRuleAttrBuilder();
109 SourcePortRangeBuilder sourcePortRangeBuilder = new SourcePortRangeBuilder();
110 DestinationPortRangeBuilder destinationPortRangeBuilder = new DestinationPortRangeBuilder();
111 boolean isDirectionIngress = false;
112 if (securityRule.getDirection() != null) {
113 securityRuleAttrBuilder.setDirection(DIRECTION_MAP.get(securityRule.getDirection()));
114 isDirectionIngress = securityRule.getDirection().equals(DirectionIngress.class);
116 if (securityRule.getPortRangeMax() != null) {
117 destinationPortRangeBuilder.setUpperPort(new PortNumber(securityRule.getPortRangeMax()));
120 if (securityRule.getPortRangeMin() != null) {
121 destinationPortRangeBuilder.setLowerPort(new PortNumber(securityRule.getPortRangeMin()));
122 // set destination port range if lower port is specified as it is mandatory parameter in acl model
123 aceIpBuilder.setDestinationPortRange(destinationPortRangeBuilder.build());
125 aceIpBuilder = handleRemoteIpPrefix(securityRule, aceIpBuilder, isDirectionIngress);
126 if (securityRule.getRemoteGroupId() != null) {
127 securityRuleAttrBuilder.setRemoteGroupId(securityRule.getRemoteGroupId());
129 if (securityRule.getProtocol() != null) {
130 SecurityRuleAttributes.Protocol protocol = securityRule.getProtocol();
131 if (protocol.getUint8() != null) {
133 aceIpBuilder.setProtocol(protocol.getUint8());
135 // symbolic protocol name
136 aceIpBuilder.setProtocol(PROTOCOL_MAP.get(protocol.getIdentityref()));
140 MatchesBuilder matchesBuilder = new MatchesBuilder();
141 matchesBuilder.setAceType(aceIpBuilder.build());
142 // set acl action as permit for the security rule
143 ActionsBuilder actionsBuilder = new ActionsBuilder();
144 actionsBuilder.setPacketHandling(new PermitBuilder().setPermit(true).build());
146 AceBuilder aceBuilder = new AceBuilder();
147 aceBuilder.setKey(new AceKey(securityRule.getUuid().getValue()));
148 aceBuilder.setRuleName(securityRule.getUuid().getValue());
149 aceBuilder.setMatches(matchesBuilder.build());
150 aceBuilder.setActions(actionsBuilder.build());
151 aceBuilder.addAugmentation(SecurityRuleAttr.class, securityRuleAttrBuilder.build());
155 private AceIpBuilder handleEtherType(SecurityRule securityRule, AceIpBuilder aceIpBuilder) {
156 if (NeutronSecurityRuleConstants.ETHERTYPE_IPV4.equals(securityRule.getEthertype())) {
157 AceIpv4Builder aceIpv4Builder = new AceIpv4Builder();
158 aceIpv4Builder.setSourceIpv4Network(new Ipv4Prefix(
159 NeutronSecurityRuleConstants.IPV4_ALL_NETWORK));
160 aceIpv4Builder.setDestinationIpv4Network(new Ipv4Prefix(
161 NeutronSecurityRuleConstants.IPV4_ALL_NETWORK));
162 aceIpBuilder.setAceIpVersion(aceIpv4Builder.build());
164 AceIpv6Builder aceIpv6Builder = new AceIpv6Builder();
165 aceIpv6Builder.setSourceIpv6Network(new Ipv6Prefix(
166 NeutronSecurityRuleConstants.IPV6_ALL_NETWORK));
167 aceIpv6Builder.setDestinationIpv6Network(new Ipv6Prefix(
168 NeutronSecurityRuleConstants.IPV6_ALL_NETWORK));
169 aceIpBuilder.setAceIpVersion(aceIpv6Builder.build());
175 private AceIpBuilder handleRemoteIpPrefix(SecurityRule securityRule, AceIpBuilder aceIpBuilder,
176 boolean isDirectionIngress) {
177 if (securityRule.getRemoteIpPrefix() != null) {
178 if (securityRule.getRemoteIpPrefix().getIpv4Prefix() != null) {
179 AceIpv4Builder aceIpv4Builder = new AceIpv4Builder();
180 if (isDirectionIngress) {
181 aceIpv4Builder.setSourceIpv4Network(new Ipv4Prefix(securityRule
182 .getRemoteIpPrefix().getIpv4Prefix().getValue()));
184 aceIpv4Builder.setDestinationIpv4Network(new Ipv4Prefix(securityRule
185 .getRemoteIpPrefix().getIpv4Prefix().getValue()));
187 aceIpBuilder.setAceIpVersion(aceIpv4Builder.build());
189 AceIpv6Builder aceIpv6Builder = new AceIpv6Builder();
190 if (isDirectionIngress) {
191 aceIpv6Builder.setSourceIpv6Network(new Ipv6Prefix(
192 securityRule.getRemoteIpPrefix().getIpv6Prefix().getValue()));
194 aceIpv6Builder.setDestinationIpv6Network(new Ipv6Prefix(
195 securityRule.getRemoteIpPrefix().getIpv6Prefix().getValue()));
197 aceIpBuilder.setAceIpVersion(aceIpv6Builder.build());
200 if (securityRule.getEthertype() != null) {
201 handleEtherType( securityRule, aceIpBuilder);
209 // TODO Clean up the exception handling
210 @SuppressWarnings("checkstyle:IllegalCatch")
211 protected void remove(InstanceIdentifier<SecurityRule> instanceIdentifier, SecurityRule securityRule) {
212 LOG.trace("removed securityRule: {}", securityRule);
214 InstanceIdentifier<Ace> identifier = getAceInstanceIdentifier(securityRule);
215 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, identifier);
216 } catch (Exception ex) {
217 LOG.error("Exception occured while removing acl for security rule: ", ex);
222 protected void update(InstanceIdentifier<SecurityRule> instanceIdentifier,
223 SecurityRule oldSecurityRule, SecurityRule updatedSecurityRule) {
224 // security rule updation is not supported from openstack, so no need to handle update.
225 LOG.trace("updates on security rules not supported.");
229 protected NeutronSecurityRuleListener getDataTreeChangeListener() {