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.inject.Inject;
20 import javax.inject.Singleton;
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;
55 public ExternalNetworkGroupInstaller(final DataBroker broker, final IMdsalApiManager mdsalManager,
56 final IElanService elanService, final IdManagerService idManager,
57 final OdlInterfaceRpcService odlInterfaceRpcService,
58 final JobCoordinator coordinator, final ItmRpcService itmRpcService,
59 final IInterfaceManager interfaceManager) {
62 this.mdsalManager = mdsalManager;
63 this.elanService = elanService;
64 this.idManager = idManager;
65 this.odlInterfaceRpcService = odlInterfaceRpcService;
66 this.coordinator = coordinator;
67 this.itmRpcService = itmRpcService;
68 this.interfaceManager = interfaceManager;
71 public void installExtNetGroupEntries(Subnetmap subnetMap) {
72 if (subnetMap == null) {
73 LOG.error("installExtNetGroupEntries : Subnetmap is null");
77 if (NatUtil.isIPv6Subnet(subnetMap.getSubnetIp())) {
78 LOG.debug("installExtNetGroupEntries : Subnet id {} is not an IPv4 subnet, hence skipping.",
83 Uuid networkId = subnetMap.getNetworkId();
84 Uuid subnetId = subnetMap.getId();
85 if (networkId == null) {
86 LOG.error("installExtNetGroupEntries : No network associated subnet id {}", subnetId.getValue());
90 String macAddress = NatUtil.getSubnetGwMac(broker, subnetId, networkId.getValue());
91 installExtNetGroupEntries(subnetMap, macAddress);
94 public void installExtNetGroupEntries(Uuid subnetId, String macAddress) {
95 Subnetmap subnetMap = NatUtil.getSubnetMap(broker, subnetId);
96 if (subnetMap == null) {
97 LOG.error("installExtNetGroupEntries : Subnetmap is null");
101 if (NatUtil.isIPv6Subnet(subnetMap.getSubnetIp())) {
102 LOG.debug("installExtNetGroupEntries : Subnet-id {} is not an IPv4 subnet, hence skipping.",
106 installExtNetGroupEntries(subnetMap, macAddress);
109 public void installExtNetGroupEntries(Uuid networkId, BigInteger dpnId) {
110 if (networkId == null) {
114 List<Uuid> subnetIds = NatUtil.getSubnetIdsFromNetworkId(broker, networkId);
115 if (subnetIds.isEmpty()) {
116 LOG.error("installExtNetGroupEntries : No subnet ids associated network id {}", networkId.getValue());
120 for (Uuid subnetId : subnetIds) {
121 String macAddress = NatUtil.getSubnetGwMac(broker, subnetId, networkId.getValue());
122 installExtNetGroupEntry(networkId, subnetId, dpnId, macAddress);
126 private void installExtNetGroupEntries(Subnetmap subnetMap, String macAddress) {
128 String subnetName = subnetMap.getId().getValue();
129 Uuid networkId = subnetMap.getNetworkId();
130 if (networkId == null) {
131 LOG.error("installExtNetGroupEntries : No network associated subnet id {}", subnetName);
135 Collection<String> extInterfaces = elanService.getExternalElanInterfaces(networkId.getValue());
136 if (extInterfaces == null || extInterfaces.isEmpty()) {
137 LOG.trace("installExtNetGroupEntries : No external ELAN interfaces attached to network:{},subnet {}",
138 networkId, subnetName);
142 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(subnetName), idManager);
144 LOG.info("installExtNetGroupEntries : Installing ext-net group {} entry for subnet {} with macAddress {} "
145 + "(extInterfaces: {})", groupId, subnetName, macAddress, Arrays.toString(extInterfaces.toArray()));
146 for (String extInterface : extInterfaces) {
147 BigInteger dpId = NatUtil.getDpnForInterface(odlInterfaceRpcService, extInterface);
148 if (BigInteger.ZERO.equals(dpId)) {
149 LOG.info("installExtNetGroupEntries: No DPN for interface {}. NAT ext-net flow will not be installed "
150 + "for subnet {}", extInterface, subnetName);
153 installExtNetGroupEntry(groupId, subnetName, extInterface, macAddress, dpId);
157 public void installExtNetGroupEntry(Uuid networkId, Uuid subnetId, BigInteger dpnId, String macAddress) {
158 String subnetName = subnetId.getValue();
159 String extInterface = elanService.getExternalElanInterface(networkId.getValue(), dpnId);
160 if (extInterface == null) {
161 LOG.warn("installExtNetGroupEntry : No external ELAN interface attached to network {} subnet {} DPN id {}",
162 networkId, subnetName, dpnId);
166 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(subnetName), idManager);
167 LOG.info("installExtNetGroupEntry : Installing ext-net group {} entry for subnet {} with macAddress {} "
168 + "(extInterface: {})", groupId, subnetName, macAddress, extInterface);
169 installExtNetGroupEntry(groupId, subnetName, extInterface, macAddress, dpnId);
172 private void installExtNetGroupEntry(long groupId, String subnetName, String extInterface,
173 String macAddress, BigInteger dpnId) {
175 coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + subnetName + extInterface, () -> {
176 GroupEntity groupEntity = buildExtNetGroupEntity(macAddress, subnetName, groupId, extInterface, dpnId);
177 if (groupEntity != null) {
178 mdsalManager.syncInstallGroup(groupEntity);
180 return Collections.emptyList();
184 public void removeExtNetGroupEntries(Subnetmap subnetMap) {
185 if (subnetMap == null) {
189 String subnetName = subnetMap.getId().getValue();
190 Uuid networkId = subnetMap.getNetworkId();
191 if (networkId == null) {
192 LOG.error("removeExtNetGroupEntries : No external network associated subnet id {}", subnetName);
196 Collection<String> extInterfaces = elanService.getExternalElanInterfaces(networkId.getValue());
197 if (extInterfaces == null || extInterfaces.isEmpty()) {
198 LOG.debug("removeExtNetGroupEntries : No external ELAN interfaces attached to network {} subnet {}",
199 networkId, subnetName);
203 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(subnetName), idManager);
205 for (String extInterface : extInterfaces) {
206 GroupEntity groupEntity = buildEmptyExtNetGroupEntity(subnetName, groupId, extInterface);
207 if (groupEntity != null) {
208 LOG.info("removeExtNetGroupEntries : Remove ext-net Group: id {}, subnet id {}", groupId, subnetName);
209 NatServiceCounters.remove_external_network_group.inc();
210 mdsalManager.syncRemoveGroup(groupEntity);
215 private GroupEntity buildExtNetGroupEntity(String macAddress, String subnetName,
216 long groupId, String extInterface, BigInteger dpnId) {
218 List<ActionInfo> actionList = new ArrayList<>();
219 final int setFieldEthDestActionPos = 0;
220 List<ActionInfo> egressActionList = new ArrayList<>();
221 if (extInterface != null) {
222 egressActionList = NatUtil.getEgressActionsForInterface(odlInterfaceRpcService, itmRpcService,
223 interfaceManager, extInterface, null, setFieldEthDestActionPos + 1);
225 if (Strings.isNullOrEmpty(macAddress) || egressActionList.isEmpty()) {
226 if (Strings.isNullOrEmpty(macAddress)) {
227 LOG.trace("buildExtNetGroupEntity : Building ext-net group {} entry with drop action since "
228 + "GW mac has not been resolved for subnet {} extInterface {}",
229 groupId, subnetName, extInterface);
231 LOG.warn("buildExtNetGroupEntity : Building ext-net group {} entry with drop action since "
232 + "no egress actions were found for subnet {} extInterface {}",
233 groupId, subnetName, extInterface);
235 actionList.add(new ActionDrop());
237 LOG.trace("Building ext-net group {} entry for subnet {} extInterface {} macAddress {}",
238 groupId, subnetName, extInterface, macAddress);
239 actionList.add(new ActionSetFieldEthernetDestination(setFieldEthDestActionPos, new MacAddress(macAddress)));
240 actionList.addAll(egressActionList);
243 List<BucketInfo> listBucketInfo = new ArrayList<>();
244 listBucketInfo.add(new BucketInfo(actionList));
245 return MDSALUtil.buildGroupEntity(dpnId, groupId, subnetName, GroupTypes.GroupAll, listBucketInfo);
248 private GroupEntity buildEmptyExtNetGroupEntity(String subnetName, long groupId, String extInterface) {
249 BigInteger dpId = NatUtil.getDpnForInterface(odlInterfaceRpcService, extInterface);
250 if (BigInteger.ZERO.equals(dpId)) {
251 LOG.error("buildEmptyExtNetGroupEntity: No DPN for interface {}. NAT ext-net flow will not be installed "
252 + "for subnet {}", extInterface, subnetName);
256 return MDSALUtil.buildGroupEntity(dpId, groupId, subnetName, GroupTypes.GroupAll, new ArrayList<>());