d2b37185d3318bfa9fc54914a82bd19ae8f2953a
[netvirt.git] / vpnservice / natservice / natservice-impl / src / main / java / org / opendaylight / netvirt / natservice / internal / ExternalNetworkGroupInstaller.java
1 /*
2  * Copyright (c) 2016 Hewlett Packard Enterprise, Co. 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.netvirt.natservice.internal;
10
11 import com.google.common.base.Strings;
12 import java.math.BigInteger;
13 import java.util.ArrayList;
14 import java.util.Arrays;
15 import java.util.Collection;
16 import java.util.List;
17 import javax.inject.Inject;
18 import javax.inject.Singleton;
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.genius.mdsalutil.ActionInfo;
21 import org.opendaylight.genius.mdsalutil.BucketInfo;
22 import org.opendaylight.genius.mdsalutil.GroupEntity;
23 import org.opendaylight.genius.mdsalutil.MDSALUtil;
24 import org.opendaylight.genius.mdsalutil.actions.ActionDrop;
25 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldEthernetDestination;
26 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
27 import org.opendaylight.netvirt.elanmanager.api.IElanService;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 @Singleton
38 public class ExternalNetworkGroupInstaller {
39     private static final Logger LOG = LoggerFactory.getLogger(ExternalNetworkGroupInstaller.class);
40     private static final long FIXED_DELAY_IN_MILLISECONDS = 4000;
41     private final DataBroker broker;
42     private final IMdsalApiManager mdsalManager;
43     private final IElanService elanService;
44     private final IdManagerService idManager;
45     private final OdlInterfaceRpcService interfaceManager;
46
47     @Inject
48     public ExternalNetworkGroupInstaller(final DataBroker broker, final IMdsalApiManager mdsalManager,
49                                      final IElanService elanService, final IdManagerService idManager,
50                                      final OdlInterfaceRpcService interfaceManager) {
51         this.broker = broker;
52         this.mdsalManager = mdsalManager;
53         this.elanService = elanService;
54         this.idManager = idManager;
55         this.interfaceManager = interfaceManager;
56     }
57
58     public void installExtNetGroupEntries(Subnetmap subnetMap) {
59         if (subnetMap == null) {
60             LOG.error("installExtNetGroupEntries : Subnetmap is null");
61             return;
62         }
63
64         if (NatUtil.isIPv6Subnet(subnetMap.getSubnetIp())) {
65             LOG.error("installExtNetGroupEntries : Subnet id {} is not an IPv4 subnet, hence skipping.",
66                     subnetMap.getId());
67             return;
68         }
69
70         Uuid networkId = subnetMap.getNetworkId();
71         Uuid subnetId = subnetMap.getId();
72         if (networkId == null) {
73             LOG.error("installExtNetGroupEntries : No network associated subnet id {}", subnetId.getValue());
74             return;
75         }
76
77         String macAddress = NatUtil.getSubnetGwMac(broker, subnetId, networkId.getValue());
78         installExtNetGroupEntries(subnetMap, macAddress);
79     }
80
81     public void installExtNetGroupEntries(Uuid subnetId, String macAddress) {
82         Subnetmap subnetMap = NatUtil.getSubnetMap(broker, subnetId);
83         if (subnetMap == null) {
84             LOG.error("installExtNetGroupEntries : Subnetmap is null");
85             return;
86         }
87
88         if (NatUtil.isIPv6Subnet(subnetMap.getSubnetIp())) {
89             LOG.warn("installExtNetGroupEntries : Subnet-id {} is not an IPv4 subnet, hence skipping.",
90                     subnetMap.getId());
91             return;
92         }
93         installExtNetGroupEntries(subnetMap, macAddress);
94     }
95
96     public void installExtNetGroupEntries(Uuid networkId, BigInteger dpnId) {
97         if (networkId == null) {
98             return;
99         }
100
101         List<Uuid> subnetIds = NatUtil.getSubnetIdsFromNetworkId(broker, networkId);
102         if (subnetIds.isEmpty()) {
103             LOG.error("installExtNetGroupEntries : No subnet ids associated network id {}", networkId.getValue());
104             return;
105         }
106
107         for (Uuid subnetId : subnetIds) {
108             String macAddress = NatUtil.getSubnetGwMac(broker, subnetId, networkId.getValue());
109             installExtNetGroupEntry(networkId, subnetId, dpnId, macAddress);
110         }
111     }
112
113     private void installExtNetGroupEntries(Subnetmap subnetMap, String macAddress) {
114
115         String subnetName = subnetMap.getId().getValue();
116         Uuid networkId = subnetMap.getNetworkId();
117         if (networkId == null) {
118             LOG.error("installExtNetGroupEntries : No network associated subnet id {}", subnetName);
119             return;
120         }
121
122         Collection<String> extInterfaces = elanService.getExternalElanInterfaces(networkId.getValue());
123         if (extInterfaces == null || extInterfaces.isEmpty()) {
124             LOG.trace("installExtNetGroupEntries : No external ELAN interfaces attached to network:{},subnet {}",
125                     networkId, subnetName);
126             return;
127         }
128
129         long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(subnetName), idManager);
130
131         LOG.info("installExtNetGroupEntries : Installing ext-net group {} entry for subnet {} with macAddress {} "
132                 + "(extInterfaces: {})", groupId, subnetName, macAddress, Arrays.toString(extInterfaces.toArray()));
133         for (String extInterface : extInterfaces) {
134             installExtNetGroupEntry(groupId, subnetName, extInterface, macAddress);
135         }
136     }
137
138     private void installExtNetGroupEntry(Uuid networkId, Uuid subnetId, BigInteger dpnId, String macAddress) {
139         String subnetName = subnetId.getValue();
140         String extInterface = elanService.getExternalElanInterface(networkId.getValue(), dpnId);
141         if (extInterface == null) {
142             LOG.error("installExtNetGroupEntry : No external ELAN interface attached to network {} subnet {} DPN id {}",
143                     networkId, subnetName, dpnId);
144             return;
145         }
146
147         long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(subnetName), idManager);
148         LOG.info("installExtNetGroupEntry : Installing ext-net group {} entry for subnet {} with macAddress {} "
149                 + "(extInterface: {})", groupId, subnetName, macAddress, extInterface);
150         installExtNetGroupEntry(groupId, subnetName, extInterface, macAddress);
151     }
152
153     private void installExtNetGroupEntry(long groupId, String subnetName, String extInterface, String macAddress) {
154         GroupEntity groupEntity = buildExtNetGroupEntity(macAddress, subnetName, groupId, extInterface);
155         if (groupEntity != null) {
156             mdsalManager.syncInstallGroup(groupEntity, FIXED_DELAY_IN_MILLISECONDS);
157         }
158     }
159
160     public void removeExtNetGroupEntries(Subnetmap subnetMap) {
161         if (subnetMap == null) {
162             return;
163         }
164
165         String subnetName = subnetMap.getId().getValue();
166         Uuid networkId = subnetMap.getNetworkId();
167         if (networkId == null) {
168             LOG.error("removeExtNetGroupEntries : No external network associated subnet id {}", subnetName);
169             return;
170         }
171
172         Collection<String> extInterfaces = elanService.getExternalElanInterfaces(networkId.getValue());
173         if (extInterfaces == null || extInterfaces.isEmpty()) {
174             LOG.error("removeExtNetGroupEntries : No external ELAN interfaces attached to network {} subnet {}",
175                     networkId, subnetName);
176             return;
177         }
178
179         long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(subnetName), idManager);
180
181         for (String extInterface : extInterfaces) {
182             GroupEntity groupEntity = buildEmptyExtNetGroupEntity(subnetName, groupId, extInterface);
183             if (groupEntity != null) {
184                 LOG.info("removeExtNetGroupEntries : Remove ext-net Group: id {}, subnet id {}", groupId, subnetName);
185                 NatServiceCounters.remove_external_network_group.inc();
186                 mdsalManager.syncRemoveGroup(groupEntity);
187             }
188         }
189     }
190
191     private GroupEntity buildExtNetGroupEntity(String macAddress, String subnetName,
192                                                long groupId, String extInterface) {
193         BigInteger dpId = NatUtil.getDpnForInterface(interfaceManager, extInterface);
194         if (BigInteger.ZERO.equals(dpId)) {
195             LOG.error("buildExtNetGroupEntity: No DPN for interface {}. NAT ext-net flow will not be installed "
196                     + "for subnet {}", extInterface, subnetName);
197             return null;
198         }
199
200         List<ActionInfo> actionList = new ArrayList<>();
201         final int setFieldEthDestActionPos = 0;
202         List<ActionInfo> egressActionList = NatUtil.getEgressActionsForInterface(interfaceManager, extInterface, null,
203                 setFieldEthDestActionPos + 1);
204
205         if (Strings.isNullOrEmpty(macAddress) || egressActionList.isEmpty()) {
206             if (Strings.isNullOrEmpty(macAddress)) {
207                 LOG.trace("buildExtNetGroupEntity : Building ext-net group {} entry with drop action since "
208                         + "GW mac has not been resolved for subnet {} extInterface {}",
209                         groupId, subnetName, extInterface);
210             } else {
211                 LOG.warn("buildExtNetGroupEntity : Building ext-net group {} entry with drop action since "
212                         + "no egress actions were found for subnet {} extInterface {}",
213                         groupId, subnetName, extInterface);
214             }
215             actionList.add(new ActionDrop());
216         } else {
217             LOG.trace("Building ext-net group {} entry for subnet {} extInterface {} macAddress {}",
218                       groupId, subnetName, extInterface, macAddress);
219             actionList.add(new ActionSetFieldEthernetDestination(setFieldEthDestActionPos, new MacAddress(macAddress)));
220             actionList.addAll(egressActionList);
221         }
222
223         List<BucketInfo> listBucketInfo = new ArrayList<>();
224         listBucketInfo.add(new BucketInfo(actionList));
225         return MDSALUtil.buildGroupEntity(dpId, groupId, subnetName, GroupTypes.GroupAll, listBucketInfo);
226     }
227
228     private GroupEntity buildEmptyExtNetGroupEntity(String subnetName, long groupId, String extInterface) {
229         BigInteger dpId = NatUtil.getDpnForInterface(interfaceManager, extInterface);
230         if (BigInteger.ZERO.equals(dpId)) {
231             LOG.error("buildEmptyExtNetGroupEntity: No DPN for interface {}. NAT ext-net flow will not be installed "
232                     + "for subnet {}", extInterface, subnetName);
233             return null;
234         }
235
236         return MDSALUtil.buildGroupEntity(dpId, groupId, subnetName, GroupTypes.GroupAll, new ArrayList<>());
237     }
238 }