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.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;
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;
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) {
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;
75 public void installExtNetGroupEntries(Subnetmap subnetMap) {
76 if (subnetMap == null) {
77 LOG.error("installExtNetGroupEntries : Subnetmap is null");
81 if (NatUtil.isIPv6Subnet(subnetMap.getSubnetIp())) {
82 LOG.debug("installExtNetGroupEntries : Subnet id {} is not an IPv4 subnet, hence skipping.",
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());
94 String macAddress = NatUtil.getSubnetGwMac(broker, subnetId, networkId.getValue());
95 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 installExtNetGroupEntries(subnetMap, macAddress);
113 public void installExtNetGroupEntries(Uuid networkId, Uint64 dpnId) {
114 if (networkId == null) {
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 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);
175 Uint32 groupId = NatUtil.getUniqueId(idManager, NatConstants.SNAT_IDPOOL_NAME,
176 NatUtil.getGroupIdKey(subnetName));
177 if (groupId != NatConstants.INVALID_ID) {
179 "installExtNetGroupEntry : Installing ext-net group {} entry for subnet {} with macAddress {} "
180 + "(extInterface: {})", groupId, subnetName, macAddress, extInterface);
181 installExtNetGroupEntry(groupId, subnetName, extInterface, macAddress, dpnId);
183 LOG.error("installExtNetGroupEntry: Unable to get groupId for subnet:{}", subnetName);
187 private void installExtNetGroupEntry(Uint32 groupId, String subnetName, String extInterface,
188 String macAddress, Uint64 dpnId) {
190 coordinator.enqueueJob(NatUtil.getDefaultFibRouteToSNATForSubnetJobKey(subnetName, dpnId), () -> {
191 GroupEntity groupEntity = buildExtNetGroupEntity(macAddress, subnetName, groupId, extInterface, dpnId);
192 mdsalManager.syncInstallGroup(groupEntity);
193 return Collections.emptyList();
197 public void removeExtNetGroupEntries(Subnetmap subnetMap) {
198 if (subnetMap == null) {
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);
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);
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,
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);
230 LOG.error("removeExtNetGroupEntries: Unable to get groupId for subnet:{}", subnetName);
234 private GroupEntity buildExtNetGroupEntity(String macAddress, String subnetName,
235 Uint32 groupId, String extInterface, Uint64 dpnId) {
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);
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);
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);
254 actionList.add(new ActionDrop());
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);
262 List<BucketInfo> listBucketInfo = new ArrayList<>();
263 listBucketInfo.add(new BucketInfo(actionList));
264 return MDSALUtil.buildGroupEntity(dpnId, groupId.longValue(), subnetName, GroupTypes.GroupAll, listBucketInfo);
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);
276 return MDSALUtil.buildGroupEntity(dpId, groupId.longValue(), subnetName,
277 GroupTypes.GroupAll, new ArrayList<>());