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;
13 import java.math.BigInteger;
14 import java.util.ArrayList;
15 import java.util.Arrays;
16 import java.util.Collection;
17 import java.util.Collections;
18 import java.util.List;
19 import javax.annotation.Nullable;
20 import javax.inject.Inject;
21 import javax.inject.Singleton;
22 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
23 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
24 import org.opendaylight.genius.mdsalutil.ActionInfo;
25 import org.opendaylight.genius.mdsalutil.BucketInfo;
26 import org.opendaylight.genius.mdsalutil.GroupEntity;
27 import org.opendaylight.genius.mdsalutil.MDSALUtil;
28 import org.opendaylight.genius.mdsalutil.actions.ActionDrop;
29 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldEthernetDestination;
30 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
31 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
32 import org.opendaylight.netvirt.elanmanager.api.IElanService;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
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, BigInteger 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 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(subnetName), idManager);
148 LOG.info("installExtNetGroupEntries : Installing ext-net group {} entry for subnet {} with macAddress {} "
149 + "(extInterfaces: {})", groupId, subnetName, macAddress, Arrays.toString(extInterfaces.toArray()));
150 for (String extInterface : extInterfaces) {
151 BigInteger dpId = NatUtil.getDpnForInterface(odlInterfaceRpcService, extInterface);
152 if (BigInteger.ZERO.equals(dpId)) {
153 LOG.info("installExtNetGroupEntries: No DPN for interface {}. NAT ext-net flow will not be installed "
154 + "for subnet {}", extInterface, subnetName);
157 installExtNetGroupEntry(groupId, subnetName, extInterface, macAddress, dpId);
161 public void installExtNetGroupEntry(Uuid networkId, Uuid subnetId, BigInteger dpnId, String macAddress) {
162 String subnetName = subnetId.getValue();
163 String extInterface = elanService.getExternalElanInterface(networkId.getValue(), dpnId);
164 if (extInterface == null) {
165 LOG.warn("installExtNetGroupEntry : No external ELAN interface attached to network {} subnet {} DPN id {}",
166 networkId, subnetName, dpnId);
170 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(subnetName), idManager);
171 LOG.info("installExtNetGroupEntry : Installing ext-net group {} entry for subnet {} with macAddress {} "
172 + "(extInterface: {})", groupId, subnetName, macAddress, extInterface);
173 installExtNetGroupEntry(groupId, subnetName, extInterface, macAddress, dpnId);
176 private void installExtNetGroupEntry(long groupId, String subnetName, String extInterface,
177 String macAddress, BigInteger dpnId) {
179 coordinator.enqueueJob(NatUtil.getDefaultFibRouteToSNATForSubnetJobKey(subnetName, dpnId), () -> {
180 GroupEntity groupEntity = buildExtNetGroupEntity(macAddress, subnetName, groupId, extInterface, dpnId);
181 mdsalManager.syncInstallGroup(groupEntity);
182 return Collections.emptyList();
186 public void removeExtNetGroupEntries(Subnetmap subnetMap) {
187 if (subnetMap == null) {
191 String subnetName = subnetMap.getId().getValue();
192 Uuid networkId = subnetMap.getNetworkId();
193 if (networkId == null) {
194 LOG.error("removeExtNetGroupEntries : No external network associated subnet id {}", subnetName);
198 Collection<String> extInterfaces = elanService.getExternalElanInterfaces(networkId.getValue());
199 if (extInterfaces == null || extInterfaces.isEmpty()) {
200 LOG.debug("removeExtNetGroupEntries : No external ELAN interfaces attached to network {} subnet {}",
201 networkId, subnetName);
205 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(subnetName), idManager);
207 for (String extInterface : extInterfaces) {
208 GroupEntity groupEntity = buildEmptyExtNetGroupEntity(subnetName, groupId, extInterface);
209 if (groupEntity != null) {
210 LOG.info("removeExtNetGroupEntries : Remove ext-net Group: id {}, subnet id {}", groupId, subnetName);
211 natServiceCounters.removeExternalNetworkGroup();
212 mdsalManager.syncRemoveGroup(groupEntity);
217 private GroupEntity buildExtNetGroupEntity(String macAddress, String subnetName,
218 long groupId, String extInterface, BigInteger dpnId) {
220 List<ActionInfo> actionList = new ArrayList<>();
221 final int setFieldEthDestActionPos = 0;
222 List<ActionInfo> egressActionList = new ArrayList<>();
223 if (extInterface != null) {
224 egressActionList = NatUtil.getEgressActionsForInterface(odlInterfaceRpcService, itmRpcService,
225 interfaceManager, extInterface, null, setFieldEthDestActionPos + 1, false);
227 if (Strings.isNullOrEmpty(macAddress) || egressActionList.isEmpty()) {
228 if (Strings.isNullOrEmpty(macAddress)) {
229 LOG.trace("buildExtNetGroupEntity : Building ext-net group {} entry with drop action since "
230 + "GW mac has not been resolved for subnet {} extInterface {}",
231 groupId, subnetName, extInterface);
233 LOG.warn("buildExtNetGroupEntity : Building ext-net group {} entry with drop action since "
234 + "no egress actions were found for subnet {} extInterface {}",
235 groupId, subnetName, extInterface);
237 actionList.add(new ActionDrop());
239 LOG.trace("Building ext-net group {} entry for subnet {} extInterface {} macAddress {}",
240 groupId, subnetName, extInterface, macAddress);
241 actionList.add(new ActionSetFieldEthernetDestination(setFieldEthDestActionPos, new MacAddress(macAddress)));
242 actionList.addAll(egressActionList);
245 List<BucketInfo> listBucketInfo = new ArrayList<>();
246 listBucketInfo.add(new BucketInfo(actionList));
247 return MDSALUtil.buildGroupEntity(dpnId, groupId, subnetName, GroupTypes.GroupAll, listBucketInfo);
251 private GroupEntity buildEmptyExtNetGroupEntity(String subnetName, long groupId, String extInterface) {
252 BigInteger dpId = NatUtil.getDpnForInterface(odlInterfaceRpcService, extInterface);
253 if (BigInteger.ZERO.equals(dpId)) {
254 LOG.error("buildEmptyExtNetGroupEntity: No DPN for interface {}. NAT ext-net flow will not be installed "
255 + "for subnet {}", extInterface, subnetName);
259 return MDSALUtil.buildGroupEntity(dpId, groupId, subnetName, GroupTypes.GroupAll, new ArrayList<>());