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.createGroupId(NatUtil.getGroupIdKey(subnetName), idManager);
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);
156 installExtNetGroupEntry(groupId, subnetName, extInterface, macAddress, dpId);
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);
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);
175 private void installExtNetGroupEntry(long groupId, String subnetName, String extInterface,
176 String macAddress, BigInteger dpnId) {
178 coordinator.enqueueJob(NatUtil.getDefaultFibRouteToSNATForSubnetJobKey(subnetName, dpnId), () -> {
179 GroupEntity groupEntity = buildExtNetGroupEntity(macAddress, subnetName, groupId, extInterface, dpnId);
180 mdsalManager.syncInstallGroup(groupEntity);
181 return Collections.emptyList();
185 public void removeExtNetGroupEntries(Subnetmap subnetMap) {
186 if (subnetMap == null) {
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);
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);
204 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(subnetName), idManager);
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);
216 private GroupEntity buildExtNetGroupEntity(String macAddress, String subnetName,
217 long groupId, String extInterface, BigInteger dpnId) {
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);
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);
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);
236 actionList.add(new ActionDrop());
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);
244 List<BucketInfo> listBucketInfo = new ArrayList<>();
245 listBucketInfo.add(new BucketInfo(actionList));
246 return MDSALUtil.buildGroupEntity(dpnId, groupId, subnetName, GroupTypes.GroupAll, listBucketInfo);
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);
258 return MDSALUtil.buildGroupEntity(dpId, groupId, subnetName, GroupTypes.GroupAll, new ArrayList<>());