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.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;
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;
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) {
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;
74 public void installExtNetGroupEntries(Subnetmap subnetMap) {
75 if (subnetMap == null) {
76 LOG.error("installExtNetGroupEntries : Subnetmap is null");
80 if (NatUtil.isIPv6Subnet(subnetMap.getSubnetIp())) {
81 LOG.debug("installExtNetGroupEntries : Subnet id {} is not an IPv4 subnet, hence skipping.",
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());
93 String macAddress = NatUtil.getSubnetGwMac(broker, subnetId, networkId.getValue());
94 installExtNetGroupEntries(subnetMap, macAddress);
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");
104 if (NatUtil.isIPv6Subnet(subnetMap.getSubnetIp())) {
105 LOG.debug("installExtNetGroupEntries : Subnet-id {} is not an IPv4 subnet, hence skipping.",
109 installExtNetGroupEntries(subnetMap, macAddress);
112 public void installExtNetGroupEntries(Uuid networkId, BigInteger dpnId) {
113 if (networkId == null) {
117 List<Uuid> subnetIds = NatUtil.getSubnetIdsFromNetworkId(broker, networkId);
118 if (subnetIds.isEmpty()) {
119 LOG.error("installExtNetGroupEntries : No subnet ids associated network id {}", networkId.getValue());
123 for (Uuid subnetId : subnetIds) {
124 String macAddress = NatUtil.getSubnetGwMac(broker, subnetId, networkId.getValue());
125 installExtNetGroupEntry(networkId, subnetId, dpnId, macAddress);
129 private void installExtNetGroupEntries(Subnetmap subnetMap, String macAddress) {
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);
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);
145 long groupId = NatUtil.getUniqueId(idManager, NatConstants.SNAT_IDPOOL_NAME,
146 NatUtil.getGroupIdKey(subnetName));
147 if (groupId != NatConstants.INVALID_ID) {
148 LOG.info("installExtNetGroupEntries : Installing ext-net group {} entry for subnet {} with macAddress {} "
149 + "(extInterfaces: {})", groupId, subnetName, macAddress,
150 Arrays.toString(extInterfaces.toArray()));
151 for (String extInterface : extInterfaces) {
152 BigInteger dpId = NatUtil.getDpnForInterface(odlInterfaceRpcService, extInterface);
153 if (BigInteger.ZERO.equals(dpId)) {
155 "installExtNetGroupEntries: No DPN for interface {}. NAT ext-net flow will not be installed "
156 + "for subnet {}", extInterface, subnetName);
159 installExtNetGroupEntry(groupId, subnetName, extInterface, macAddress, dpId);
162 LOG.error("installExtNetGroupEntries: Unable to get groupId for subnet:{}", subnetName);
166 public void installExtNetGroupEntry(Uuid networkId, Uuid subnetId, BigInteger dpnId, String macAddress) {
167 String subnetName = subnetId.getValue();
168 String extInterface = elanService.getExternalElanInterface(networkId.getValue(), dpnId);
169 if (extInterface == null) {
170 LOG.warn("installExtNetGroupEntry : No external ELAN interface attached to network {} subnet {} DPN id {}",
171 networkId, subnetName, dpnId);
174 long groupId = NatUtil.getUniqueId(idManager, NatConstants.SNAT_IDPOOL_NAME, NatUtil.getGroupIdKey(subnetName));
175 if (groupId != NatConstants.INVALID_ID) {
177 "installExtNetGroupEntry : Installing ext-net group {} entry for subnet {} with macAddress {} "
178 + "(extInterface: {})", groupId, subnetName, macAddress, extInterface);
179 installExtNetGroupEntry(groupId, subnetName, extInterface, macAddress, dpnId);
181 LOG.error("installExtNetGroupEntry: Unable to get groupId for subnet:{}", subnetName);
185 private void installExtNetGroupEntry(long groupId, String subnetName, String extInterface,
186 String macAddress, BigInteger dpnId) {
188 coordinator.enqueueJob(NatUtil.getDefaultFibRouteToSNATForSubnetJobKey(subnetName, dpnId), () -> {
189 GroupEntity groupEntity = buildExtNetGroupEntity(macAddress, subnetName, groupId, extInterface, dpnId);
190 mdsalManager.syncInstallGroup(groupEntity);
191 return Collections.emptyList();
195 public void removeExtNetGroupEntries(Subnetmap subnetMap) {
196 if (subnetMap == null) {
200 String subnetName = subnetMap.getId().getValue();
201 Uuid networkId = subnetMap.getNetworkId();
202 if (networkId == null) {
203 LOG.error("removeExtNetGroupEntries : No external network associated subnet id {}", subnetName);
207 Collection<String> extInterfaces = elanService.getExternalElanInterfaces(networkId.getValue());
208 if (extInterfaces == null || extInterfaces.isEmpty()) {
209 LOG.debug("removeExtNetGroupEntries : No external ELAN interfaces attached to network {} subnet {}",
210 networkId, subnetName);
214 long groupId = NatUtil.getUniqueId(idManager, NatConstants.SNAT_IDPOOL_NAME, NatUtil.getGroupIdKey(subnetName));
215 if (groupId != NatConstants.INVALID_ID) {
216 for (String extInterface : extInterfaces) {
217 GroupEntity groupEntity = buildEmptyExtNetGroupEntity(subnetName, groupId,
219 if (groupEntity != null) {
220 LOG.info("removeExtNetGroupEntries : Remove ext-net Group: id {}, subnet id {}",
221 groupId, subnetName);
222 natServiceCounters.removeExternalNetworkGroup();
223 mdsalManager.syncRemoveGroup(groupEntity);
227 LOG.error("removeExtNetGroupEntries: Unable to get groupId for subnet:{}", subnetName);
231 private GroupEntity buildExtNetGroupEntity(String macAddress, String subnetName,
232 long groupId, String extInterface, BigInteger dpnId) {
234 List<ActionInfo> actionList = new ArrayList<>();
235 final int setFieldEthDestActionPos = 0;
236 List<ActionInfo> egressActionList = new ArrayList<>();
237 if (extInterface != null) {
238 egressActionList = NatUtil.getEgressActionsForInterface(odlInterfaceRpcService, itmRpcService,
239 interfaceManager, extInterface, null, setFieldEthDestActionPos + 1, false);
241 if (Strings.isNullOrEmpty(macAddress) || egressActionList.isEmpty()) {
242 if (Strings.isNullOrEmpty(macAddress)) {
243 LOG.trace("buildExtNetGroupEntity : Building ext-net group {} entry with drop action since "
244 + "GW mac has not been resolved for subnet {} extInterface {}",
245 groupId, subnetName, extInterface);
247 LOG.warn("buildExtNetGroupEntity : Building ext-net group {} entry with drop action since "
248 + "no egress actions were found for subnet {} extInterface {}",
249 groupId, subnetName, extInterface);
251 actionList.add(new ActionDrop());
253 LOG.trace("Building ext-net group {} entry for subnet {} extInterface {} macAddress {}",
254 groupId, subnetName, extInterface, macAddress);
255 actionList.add(new ActionSetFieldEthernetDestination(setFieldEthDestActionPos, new MacAddress(macAddress)));
256 actionList.addAll(egressActionList);
259 List<BucketInfo> listBucketInfo = new ArrayList<>();
260 listBucketInfo.add(new BucketInfo(actionList));
261 return MDSALUtil.buildGroupEntity(dpnId, groupId, subnetName, GroupTypes.GroupAll, listBucketInfo);
265 private GroupEntity buildEmptyExtNetGroupEntity(String subnetName, long groupId, String extInterface) {
266 BigInteger dpId = NatUtil.getDpnForInterface(odlInterfaceRpcService, extInterface);
267 if (BigInteger.ZERO.equals(dpId)) {
268 LOG.error("buildEmptyExtNetGroupEntity: No DPN for interface {}. NAT ext-net flow will not be installed "
269 + "for subnet {}", extInterface, subnetName);
273 return MDSALUtil.buildGroupEntity(dpId, groupId, subnetName, GroupTypes.GroupAll, new ArrayList<>());