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