2 * Copyright (c) 2016 Hewlett Packard Enterprise, Co. 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
9 package org.opendaylight.netvirt.natservice.internal;
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.NetworkAttributes;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
39 import org.opendaylight.yangtools.yang.common.Uint32;
40 import org.opendaylight.yangtools.yang.common.Uint64;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
45 public class ExternalNetworkGroupInstaller {
46 private static final Logger LOG = LoggerFactory.getLogger(ExternalNetworkGroupInstaller.class);
47 private final DataBroker broker;
48 private final IMdsalApiManager mdsalManager;
49 private final IElanService elanService;
50 private final IdManagerService idManager;
51 private final OdlInterfaceRpcService odlInterfaceRpcService;
52 private final JobCoordinator coordinator;
53 private final ItmRpcService itmRpcService;
54 private final IInterfaceManager interfaceManager;
55 private final NatServiceCounters natServiceCounters;
58 public ExternalNetworkGroupInstaller(final DataBroker broker, final IMdsalApiManager mdsalManager,
59 final IElanService elanService, final IdManagerService idManager,
60 final OdlInterfaceRpcService odlInterfaceRpcService,
61 final JobCoordinator coordinator, final ItmRpcService itmRpcService,
62 final IInterfaceManager interfaceManager,
63 NatServiceCounters natServiceCounters) {
66 this.mdsalManager = mdsalManager;
67 this.elanService = elanService;
68 this.idManager = idManager;
69 this.odlInterfaceRpcService = odlInterfaceRpcService;
70 this.coordinator = coordinator;
71 this.itmRpcService = itmRpcService;
72 this.interfaceManager = interfaceManager;
73 this.natServiceCounters = natServiceCounters;
76 public void installExtNetGroupEntries(Subnetmap subnetMap) {
77 if (subnetMap == null) {
78 LOG.error("installExtNetGroupEntries : Subnetmap is null");
82 if (NatUtil.isIPv6Subnet(subnetMap.getSubnetIp())) {
83 LOG.debug("installExtNetGroupEntries : Subnet id {} is not an IPv4 subnet, hence skipping.",
88 Uuid networkId = subnetMap.getNetworkId();
89 Uuid subnetId = subnetMap.getId();
90 NetworkAttributes.NetworkType extNetworkType = subnetMap.getNetworkType();
91 if (externalGroupInstallationRequiredForExtNetwork(networkId, subnetMap.isExternal(),
92 extNetworkType, subnetId)) {
93 String macAddress = NatUtil.getSubnetGwMac(broker, subnetId, networkId.getValue());
94 installExtNetGroupEntries(subnetMap, macAddress);
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");
105 if (NatUtil.isIPv6Subnet(subnetMap.getSubnetIp())) {
106 LOG.debug("installExtNetGroupEntries : Subnet-id {} is not an IPv4 subnet, hence skipping.",
110 if (externalGroupInstallationRequiredForExtNetwork(subnetMap.getNetworkId(), subnetMap.isExternal(),
111 subnetMap.getNetworkType(), subnetId)) {
112 installExtNetGroupEntries(subnetMap, macAddress);
116 public void installExtNetGroupEntries(Uuid networkId, Uint64 dpnId) {
118 List<Uuid> subnetIds = NatUtil.getSubnetIdsFromNetworkId(broker, networkId);
119 if (subnetIds.isEmpty()) {
120 LOG.error("installExtNetGroupEntries : No subnet ids associated network id {}", networkId.getValue());
124 for (Uuid subnetId : subnetIds) {
125 String macAddress = NatUtil.getSubnetGwMac(broker, subnetId, networkId.getValue());
126 installExtNetGroupEntry(networkId, subnetId, dpnId, macAddress);
130 private void installExtNetGroupEntries(Subnetmap subnetMap, String macAddress) {
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);
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);
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)) {
156 "installExtNetGroupEntries: No DPN for interface {}. NAT ext-net flow will not be installed "
157 + "for subnet {}", extInterface, subnetName);
160 installExtNetGroupEntry(groupId, subnetName, extInterface, macAddress, dpId);
163 LOG.error("installExtNetGroupEntries: Unable to get groupId for subnet:{}", subnetName);
167 public void installExtNetGroupEntry(Uuid networkId, Uuid subnetId, Uint64 dpnId, String macAddress) {
168 Subnetmap subnetMap = NatUtil.getSubnetMap(broker, subnetId);
169 if (subnetMap == null) {
170 LOG.error("installExtNetGroupEntries : Subnetmap is null");
173 if (externalGroupInstallationRequiredForExtNetwork(networkId, subnetMap.isExternal(),
174 subnetMap.getNetworkType(), subnetId)) {
175 String subnetName = subnetId.getValue();
176 String extInterface = elanService.getExternalElanInterface(networkId.getValue(), dpnId);
177 if (extInterface == null) {
179 "installExtNetGroupEntry : No external ELAN interface attached to network {} subnet {} DPN id {}",
180 networkId, subnetName, dpnId);
183 Uint32 groupId = NatUtil.getUniqueId(idManager, NatConstants.SNAT_IDPOOL_NAME,
184 NatUtil.getGroupIdKey(subnetName));
185 if (groupId != NatConstants.INVALID_ID) {
187 "installExtNetGroupEntry : Installing ext-net group {} entry for subnet {} with macAddress {} "
188 + "(extInterface: {})", groupId, subnetName, macAddress, extInterface);
189 installExtNetGroupEntry(groupId, subnetName, extInterface, macAddress, dpnId);
191 LOG.error("installExtNetGroupEntry: Unable to get groupId for subnet:{}",
197 private void installExtNetGroupEntry(Uint32 groupId, String subnetName, String extInterface,
198 String macAddress, Uint64 dpnId) {
200 coordinator.enqueueJob(NatUtil.getDefaultFibRouteToSNATForSubnetJobKey(subnetName, dpnId), () -> {
201 GroupEntity groupEntity = buildExtNetGroupEntity(macAddress, subnetName, groupId, extInterface, dpnId);
202 mdsalManager.syncInstallGroup(groupEntity);
203 return Collections.emptyList();
207 public void removeExtNetGroupEntries(Subnetmap subnetMap) {
208 if (subnetMap == null) {
212 String subnetName = subnetMap.getId().getValue();
213 Uuid networkId = subnetMap.getNetworkId();
214 NetworkAttributes.NetworkType extNetworkType = subnetMap.getNetworkType();
215 if (externalGroupInstallationRequiredForExtNetwork(networkId, subnetMap.isExternal(),
216 extNetworkType, subnetMap.getId())) {
217 Collection<String> extInterfaces = elanService.getExternalElanInterfaces(networkId.getValue());
218 if (extInterfaces == null || extInterfaces.isEmpty()) {
220 "removeExtNetGroupEntries : No external ELAN interfaces attached to network {} subnet {}",
221 networkId, subnetName);
225 Uint32 groupId = NatUtil.getUniqueId(idManager, NatConstants.SNAT_IDPOOL_NAME,
226 NatUtil.getGroupIdKey(subnetName));
227 if (groupId != NatConstants.INVALID_ID) {
228 for (String extInterface : extInterfaces) {
229 GroupEntity groupEntity = buildEmptyExtNetGroupEntity(subnetName, groupId,
231 if (groupEntity != null) {
233 "removeExtNetGroupEntries : Remove ext-net Group: id {}, subnet id {}",
234 groupId, subnetName);
235 natServiceCounters.removeExternalNetworkGroup();
236 mdsalManager.syncRemoveGroup(groupEntity);
240 LOG.error("removeExtNetGroupEntries: Unable to get groupId for subnet:{}",
246 private GroupEntity buildExtNetGroupEntity(String macAddress, String subnetName,
247 Uint32 groupId, String extInterface, Uint64 dpnId) {
249 List<ActionInfo> actionList = new ArrayList<>();
250 final int setFieldEthDestActionPos = 0;
251 List<ActionInfo> egressActionList = new ArrayList<>();
252 if (extInterface != null) {
253 egressActionList = NatUtil.getEgressActionsForInterface(odlInterfaceRpcService, itmRpcService,
254 interfaceManager, extInterface, null, setFieldEthDestActionPos + 1, false);
256 if (Strings.isNullOrEmpty(macAddress) || egressActionList.isEmpty()) {
257 if (Strings.isNullOrEmpty(macAddress)) {
258 LOG.trace("buildExtNetGroupEntity : Building ext-net group {} entry with drop action since "
259 + "GW mac has not been resolved for subnet {} extInterface {}",
260 groupId, subnetName, extInterface);
262 LOG.warn("buildExtNetGroupEntity : Building ext-net group {} entry with drop action since "
263 + "no egress actions were found for subnet {} extInterface {}",
264 groupId, subnetName, extInterface);
266 actionList.add(new ActionDrop());
268 LOG.trace("Building ext-net group {} entry for subnet {} extInterface {} macAddress {}",
269 groupId, subnetName, extInterface, macAddress);
270 actionList.add(new ActionSetFieldEthernetDestination(setFieldEthDestActionPos, new MacAddress(macAddress)));
271 actionList.addAll(egressActionList);
274 List<BucketInfo> listBucketInfo = new ArrayList<>();
275 listBucketInfo.add(new BucketInfo(actionList));
276 return MDSALUtil.buildGroupEntity(dpnId, groupId.longValue(), subnetName, GroupTypes.GroupAll, listBucketInfo);
280 private GroupEntity buildEmptyExtNetGroupEntity(String subnetName, Uint32 groupId, String extInterface) {
281 Uint64 dpId = NatUtil.getDpnForInterface(odlInterfaceRpcService, extInterface);
282 if (Uint64.ZERO.equals(dpId)) {
283 LOG.error("buildEmptyExtNetGroupEntity: No DPN for interface {}. NAT ext-net flow will not be installed "
284 + "for subnet {}", extInterface, subnetName);
288 return MDSALUtil.buildGroupEntity(dpId, groupId.longValue(), subnetName,
289 GroupTypes.GroupAll, new ArrayList<>());
292 private boolean externalGroupInstallationRequiredForExtNetwork(Uuid networkId, boolean isExternal,
293 NetworkAttributes.NetworkType extNetworkType,
295 if (networkId == null || !isExternal) {
296 LOG.debug("externalGroupInstallationRequiredForExtNetwork : network is null or not External Network:{} for"
297 + " subnet id {}", isExternal, subnetId.getValue());
300 // Installation of External Network Group is only required for flat/vlan use-cases.
301 if (extNetworkType == null
302 || extNetworkType == NetworkAttributes.NetworkType.GRE
303 || extNetworkType == NetworkAttributes.NetworkType.VXLAN) {
304 LOG.debug("Provider Type is either null or of type {} for network {}, subnet {} for which "
305 + "ExternalNetwork Group installation not required",
306 extNetworkType, networkId.getValue(), subnetId.getValue());