2 * Copyright © 2016, 2017 Ericsson India Global Services Pvt Ltd. 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
8 package org.opendaylight.netvirt.natservice.internal;
10 import java.net.InetAddress;
11 import java.net.UnknownHostException;
12 import java.util.ArrayList;
13 import java.util.Collections;
14 import java.util.List;
16 import java.util.concurrent.ExecutionException;
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.infra.Datastore.Configuration;
22 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
23 import org.opendaylight.genius.infra.TypedWriteTransaction;
24 import org.opendaylight.genius.mdsalutil.FlowEntity;
25 import org.opendaylight.genius.mdsalutil.InstructionInfo;
26 import org.opendaylight.genius.mdsalutil.MDSALUtil;
27 import org.opendaylight.genius.mdsalutil.MatchInfo;
28 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
29 import org.opendaylight.genius.mdsalutil.NwConstants;
30 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
31 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
32 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
33 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
34 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
35 import org.opendaylight.netvirt.natservice.api.NatSwitchCache;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.Subnets;
39 import org.opendaylight.yangtools.yang.common.Uint32;
40 import org.opendaylight.yangtools.yang.common.Uint64;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
45 public class SNATDefaultRouteProgrammer {
47 private static final Logger LOG = LoggerFactory.getLogger(SNATDefaultRouteProgrammer.class);
48 private final IMdsalApiManager mdsalManager;
49 private final DataBroker dataBroker;
50 private final IdManagerService idManager;
51 private final ExternalNetworkGroupInstaller extNetGroupInstaller;
52 private final NatServiceCounters natServiceCounters;
53 private final JobCoordinator jobCoordinator;
54 private final NatSwitchCache natSwitchCache;
57 public SNATDefaultRouteProgrammer(final IMdsalApiManager mdsalManager, final DataBroker dataBroker,
58 final IdManagerService idManager, final ExternalNetworkGroupInstaller extNetGroupInstaller,
59 NatServiceCounters natServiceCounters, final JobCoordinator jobCoordinator,
60 final NatSwitchCache natSwitchCache) {
61 this.mdsalManager = mdsalManager;
62 this.dataBroker = dataBroker;
63 this.idManager = idManager;
64 this.extNetGroupInstaller = extNetGroupInstaller;
65 this.natServiceCounters = natServiceCounters;
66 this.jobCoordinator = jobCoordinator;
67 this.natSwitchCache = natSwitchCache;
71 private FlowEntity buildDefNATFlowEntity(Uint64 dpId, Uint32 vpnId) {
72 InetAddress defaultIP = null;
74 defaultIP = InetAddress.getByName("0.0.0.0");
75 } catch (UnknownHostException e) {
76 LOG.error("buildDefNATFlowEntity : Failed to build FIB Table Flow for "
77 + "Default Route to NAT table", e);
81 List<MatchInfo> matches = new ArrayList<>();
82 matches.add(MatchEthernetType.IPV4);
84 //add match for default route "0.0.0.0/0"
85 // matches.add(new MatchInfo(MatchFieldType.ipv4_dst, new long[] {
86 // NatUtil.getIpAddress(defaultIP.getAddress()), 0 }));
89 matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(vpnId.longValue()),
90 MetaDataUtil.METADATA_MASK_VRFID));
92 List<InstructionInfo> instructions = new ArrayList<>();
93 instructions.add(new InstructionGotoTable(NwConstants.PSNAT_TABLE));
95 String flowRef = NatUtil.getFlowRef(dpId, NwConstants.L3_FIB_TABLE, defaultIP, vpnId);
97 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_FIB_TABLE, flowRef,
98 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
99 NwConstants.COOKIE_DNAT_TABLE, matches, instructions);
105 private FlowEntity buildDefNATFlowEntity(Uint64 dpId, Uint32 bgpVpnId, Uint32 routerId) {
106 InetAddress defaultIP = null;
108 defaultIP = InetAddress.getByName("0.0.0.0");
109 } catch (UnknownHostException e) {
110 LOG.error("buildDefNATFlowEntity : Failed to build FIB Table Flow for "
111 + "Default Route to NAT table", e);
115 List<MatchInfo> matches = new ArrayList<>();
116 matches.add(MatchEthernetType.IPV4);
118 //add match for default route "0.0.0.0/0"
119 // matches.add(new MatchInfo(MatchFieldType.ipv4_dst, new long[] {
120 // NatUtil.getIpAddress(defaultIP.getAddress()), 0 }));
122 //add match for vrfid
123 matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(bgpVpnId.longValue()),
124 MetaDataUtil.METADATA_MASK_VRFID));
126 List<InstructionInfo> instructions = new ArrayList<>();
127 instructions.add(new InstructionGotoTable(NwConstants.PSNAT_TABLE));
129 String flowRef = NatUtil.getFlowRef(dpId, NwConstants.L3_FIB_TABLE, defaultIP, routerId);
131 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_FIB_TABLE, flowRef,
132 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
133 NwConstants.COOKIE_DNAT_TABLE, matches, instructions);
140 public void installDefNATRouteInDPN(Uint64 dpnId, Uint32 vpnId, TypedWriteTransaction<Configuration> confTx) {
141 FlowEntity flowEntity = buildDefNATFlowEntity(dpnId, vpnId);
142 if (flowEntity == null) {
143 LOG.error("installDefNATRouteInDPN : Flow entity received is NULL."
144 + "Cannot proceed with installation of Default NAT flow");
147 natServiceCounters.installDefaultNatFlow();
148 mdsalManager.addFlow(confTx, flowEntity);
151 public void installDefNATRouteInDPN(Uint64 dpnId, Uint32 bgpVpnId, Uint32 routerId,
152 TypedWriteTransaction<Configuration> confTx) {
153 FlowEntity flowEntity = buildDefNATFlowEntity(dpnId, bgpVpnId, routerId);
154 if (flowEntity == null) {
155 LOG.error("installDefNATRouteInDPN : Flow entity received is NULL."
156 + "Cannot proceed with installation of Default NAT flow");
159 natServiceCounters.installDefaultNatFlow();
160 mdsalManager.addFlow(confTx, flowEntity);
163 public void installDefNATRouteInDPN(Uint64 dpnId, Uint32 vpnId, String subnetId) {
164 FlowEntity flowEntity = NatUtil.buildDefaultNATFlowEntityForExternalSubnet(dpnId, vpnId, subnetId, idManager);
165 if (flowEntity == null) {
166 LOG.error("installDefNATRouteInDPN : Flow entity received is NULL."
167 + "Cannot proceed with installation of Default NAT flow");
170 natServiceCounters.installDefaultNatFlow();
171 mdsalManager.installFlow(flowEntity);
174 public void removeDefNATRouteInDPN(Uint64 dpnId, Uint32 vpnId, TypedReadWriteTransaction<Configuration> confTx)
175 throws ExecutionException, InterruptedException {
176 FlowEntity flowEntity = buildDefNATFlowEntity(dpnId, vpnId);
177 if (flowEntity == null) {
178 LOG.error("removeDefNATRouteInDPN : Flow entity received is NULL."
179 + "Cannot proceed with installation of Default NAT flow");
182 natServiceCounters.removeDefaultNatFlow();
183 mdsalManager.removeFlow(confTx, flowEntity);
186 public void removeDefNATRouteInDPN(Uint64 dpnId, Uint32 bgpVpnId, Uint32 routerId,
187 TypedReadWriteTransaction<Configuration> confTx) throws ExecutionException, InterruptedException {
188 FlowEntity flowEntity = buildDefNATFlowEntity(dpnId, bgpVpnId, routerId);
189 if (flowEntity == null) {
190 LOG.error("removeDefNATRouteInDPN : Flow entity received is NULL."
191 + "Cannot proceed with installation of Default NAT flow");
194 natServiceCounters.removeDefaultNatFlow();
195 mdsalManager.removeFlow(confTx, flowEntity);
198 public void addOrDelDefaultFibRouteToSNATForSubnet(Subnets subnet, String networkId, int flowAction, Uint32 vpnId) {
199 String providerNet = NatUtil.getElanInstancePhysicalNetwok(networkId, dataBroker);
200 Set<Uint64> dpnList = natSwitchCache.getSwitchesConnectedToExternal(providerNet);
202 for (Uint64 dpn : dpnList) {
203 addOrDelDefaultFibRouteToSNATForSubnetInDpn(subnet, networkId, flowAction, vpnId, dpn);
207 public void addOrDelDefaultFibRouteToSNATForSubnetInDpn(Subnets subnet, String networkId, int flowAction,
208 Uint32 vpnId, Uint64 dpn) {
209 String subnetId = subnet.getId().getValue();
210 String macAddress = NatUtil.getSubnetGwMac(dataBroker, subnet.getId(), networkId);
211 extNetGroupInstaller.installExtNetGroupEntry(new Uuid(networkId), subnet.getId(),
213 FlowEntity flowEntity = NatUtil.buildDefaultNATFlowEntityForExternalSubnet(dpn,
214 vpnId, subnetId, idManager);
215 if (flowAction == NwConstants.ADD_FLOW || flowAction == NwConstants.MOD_FLOW) {
216 LOG.info("addOrDelDefaultFibRouteToSNATForSubnet : Installing flow {} for subnetId {},"
217 + "vpnId {} on dpn {}", flowEntity, subnetId, vpnId, dpn);
218 jobCoordinator.enqueueJob(NatUtil.getDefaultFibRouteToSNATForSubnetJobKey(subnetId, dpn),
219 () -> Collections.singletonList(mdsalManager.installFlow(flowEntity)));
221 LOG.info("addOrDelDefaultFibRouteToSNATForSubnet : Removing flow for subnetId {},"
222 + "vpnId {} with dpn {}", subnetId, vpnId, dpn);
223 jobCoordinator.enqueueJob(NatUtil.getDefaultFibRouteToSNATForSubnetJobKey(subnetId, dpn),
224 () -> Collections.singletonList(mdsalManager.removeFlow(flowEntity)));