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