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;
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(NatConstants.NAT_DJC_PREFIX + subnetName + extInterface, () -> {
179 GroupEntity groupEntity = buildExtNetGroupEntity(macAddress, subnetName, groupId, extInterface, dpnId);
180 if (groupEntity != null) {
181 mdsalManager.syncInstallGroup(groupEntity);
183 return Collections.emptyList();
187 public void removeExtNetGroupEntries(Subnetmap subnetMap) {
188 if (subnetMap == null) {
192 String subnetName = subnetMap.getId().getValue();
193 Uuid networkId = subnetMap.getNetworkId();
194 if (networkId == null) {
195 LOG.error("removeExtNetGroupEntries : No external network associated subnet id {}", subnetName);
199 Collection<String> extInterfaces = elanService.getExternalElanInterfaces(networkId.getValue());
200 if (extInterfaces == null || extInterfaces.isEmpty()) {
201 LOG.debug("removeExtNetGroupEntries : No external ELAN interfaces attached to network {} subnet {}",
202 networkId, subnetName);
206 long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(subnetName), idManager);
208 for (String extInterface : extInterfaces) {
209 GroupEntity groupEntity = buildEmptyExtNetGroupEntity(subnetName, groupId, extInterface);
210 if (groupEntity != null) {
211 LOG.info("removeExtNetGroupEntries : Remove ext-net Group: id {}, subnet id {}", groupId, subnetName);
212 natServiceCounters.removeExternalNetworkGroup();
213 mdsalManager.syncRemoveGroup(groupEntity);
218 private GroupEntity buildExtNetGroupEntity(String macAddress, String subnetName,
219 long groupId, String extInterface, BigInteger dpnId) {
221 List<ActionInfo> actionList = new ArrayList<>();
222 final int setFieldEthDestActionPos = 0;
223 List<ActionInfo> egressActionList = new ArrayList<>();
224 if (extInterface != null) {
225 egressActionList = NatUtil.getEgressActionsForInterface(odlInterfaceRpcService, itmRpcService,
226 interfaceManager, extInterface, null, setFieldEthDestActionPos + 1, false);
228 if (Strings.isNullOrEmpty(macAddress) || egressActionList.isEmpty()) {
229 if (Strings.isNullOrEmpty(macAddress)) {
230 LOG.trace("buildExtNetGroupEntity : Building ext-net group {} entry with drop action since "
231 + "GW mac has not been resolved for subnet {} extInterface {}",
232 groupId, subnetName, extInterface);
234 LOG.warn("buildExtNetGroupEntity : Building ext-net group {} entry with drop action since "
235 + "no egress actions were found for subnet {} extInterface {}",
236 groupId, subnetName, extInterface);
238 actionList.add(new ActionDrop());
240 LOG.trace("Building ext-net group {} entry for subnet {} extInterface {} macAddress {}",
241 groupId, subnetName, extInterface, macAddress);
242 actionList.add(new ActionSetFieldEthernetDestination(setFieldEthDestActionPos, new MacAddress(macAddress)));
243 actionList.addAll(egressActionList);
246 List<BucketInfo> listBucketInfo = new ArrayList<>();
247 listBucketInfo.add(new BucketInfo(actionList));
248 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<>());