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.math.BigInteger;
11 import java.net.InetAddress;
12 import java.net.UnknownHostException;
13 import java.util.ArrayList;
14 import java.util.Collections;
15 import java.util.List;
17 import java.util.concurrent.ExecutionException;
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.infra.Datastore.Configuration;
23 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
24 import org.opendaylight.genius.infra.TypedWriteTransaction;
25 import org.opendaylight.genius.mdsalutil.FlowEntity;
26 import org.opendaylight.genius.mdsalutil.InstructionInfo;
27 import org.opendaylight.genius.mdsalutil.MDSALUtil;
28 import org.opendaylight.genius.mdsalutil.MatchInfo;
29 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
30 import org.opendaylight.genius.mdsalutil.NwConstants;
31 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
32 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
33 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
34 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
35 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
36 import org.opendaylight.netvirt.natservice.api.NatSwitchCache;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.Subnets;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
44 public class SNATDefaultRouteProgrammer {
46 private static final Logger LOG = LoggerFactory.getLogger(SNATDefaultRouteProgrammer.class);
47 private final IMdsalApiManager mdsalManager;
48 private final DataBroker dataBroker;
49 private final IdManagerService idManager;
50 private final ExternalNetworkGroupInstaller extNetGroupInstaller;
51 private final NatServiceCounters natServiceCounters;
52 private final JobCoordinator jobCoordinator;
53 private final NatSwitchCache natSwitchCache;
56 public SNATDefaultRouteProgrammer(final IMdsalApiManager mdsalManager, final DataBroker dataBroker,
57 final IdManagerService idManager, final ExternalNetworkGroupInstaller extNetGroupInstaller,
58 NatServiceCounters natServiceCounters, final JobCoordinator jobCoordinator,
59 final NatSwitchCache natSwitchCache) {
60 this.mdsalManager = mdsalManager;
61 this.dataBroker = dataBroker;
62 this.idManager = idManager;
63 this.extNetGroupInstaller = extNetGroupInstaller;
64 this.natServiceCounters = natServiceCounters;
65 this.jobCoordinator = jobCoordinator;
66 this.natSwitchCache = natSwitchCache;
70 private FlowEntity buildDefNATFlowEntity(BigInteger dpId, long vpnId) {
71 InetAddress defaultIP = null;
73 defaultIP = InetAddress.getByName("0.0.0.0");
74 } catch (UnknownHostException e) {
75 LOG.error("buildDefNATFlowEntity : Failed to build FIB Table Flow for "
76 + "Default Route to NAT table", e);
80 List<MatchInfo> matches = new ArrayList<>();
81 matches.add(MatchEthernetType.IPV4);
83 //add match for default route "0.0.0.0/0"
84 // matches.add(new MatchInfo(MatchFieldType.ipv4_dst, new long[] {
85 // NatUtil.getIpAddress(defaultIP.getAddress()), 0 }));
88 matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(vpnId), MetaDataUtil.METADATA_MASK_VRFID));
90 List<InstructionInfo> instructions = new ArrayList<>();
91 instructions.add(new InstructionGotoTable(NwConstants.PSNAT_TABLE));
93 String flowRef = NatUtil.getFlowRef(dpId, NwConstants.L3_FIB_TABLE, defaultIP, vpnId);
95 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_FIB_TABLE, flowRef,
96 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
97 NwConstants.COOKIE_DNAT_TABLE, matches, instructions);
103 private FlowEntity buildDefNATFlowEntity(BigInteger dpId, long bgpVpnId, long routerId) {
104 InetAddress defaultIP = null;
106 defaultIP = InetAddress.getByName("0.0.0.0");
107 } catch (UnknownHostException e) {
108 LOG.error("buildDefNATFlowEntity : Failed to build FIB Table Flow for "
109 + "Default Route to NAT table", e);
113 List<MatchInfo> matches = new ArrayList<>();
114 matches.add(MatchEthernetType.IPV4);
116 //add match for default route "0.0.0.0/0"
117 // matches.add(new MatchInfo(MatchFieldType.ipv4_dst, new long[] {
118 // NatUtil.getIpAddress(defaultIP.getAddress()), 0 }));
120 //add match for vrfid
121 matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(bgpVpnId), MetaDataUtil.METADATA_MASK_VRFID));
123 List<InstructionInfo> instructions = new ArrayList<>();
124 instructions.add(new InstructionGotoTable(NwConstants.PSNAT_TABLE));
126 String flowRef = NatUtil.getFlowRef(dpId, NwConstants.L3_FIB_TABLE, defaultIP, routerId);
128 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_FIB_TABLE, flowRef,
129 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
130 NwConstants.COOKIE_DNAT_TABLE, matches, instructions);
137 public void installDefNATRouteInDPN(BigInteger dpnId, long vpnId, TypedWriteTransaction<Configuration> confTx) {
138 FlowEntity flowEntity = buildDefNATFlowEntity(dpnId, vpnId);
139 if (flowEntity == null) {
140 LOG.error("installDefNATRouteInDPN : Flow entity received is NULL."
141 + "Cannot proceed with installation of Default NAT flow");
144 natServiceCounters.installDefaultNatFlow();
145 mdsalManager.addFlow(confTx, flowEntity);
148 public void installDefNATRouteInDPN(BigInteger dpnId, long bgpVpnId, long routerId,
149 TypedWriteTransaction<Configuration> confTx) {
150 FlowEntity flowEntity = buildDefNATFlowEntity(dpnId, bgpVpnId, routerId);
151 if (flowEntity == null) {
152 LOG.error("installDefNATRouteInDPN : Flow entity received is NULL."
153 + "Cannot proceed with installation of Default NAT flow");
156 natServiceCounters.installDefaultNatFlow();
157 mdsalManager.addFlow(confTx, flowEntity);
160 public void installDefNATRouteInDPN(BigInteger dpnId, long vpnId, String subnetId) {
161 FlowEntity flowEntity = NatUtil.buildDefaultNATFlowEntityForExternalSubnet(dpnId, vpnId, subnetId, idManager);
162 if (flowEntity == null) {
163 LOG.error("installDefNATRouteInDPN : Flow entity received is NULL."
164 + "Cannot proceed with installation of Default NAT flow");
167 natServiceCounters.installDefaultNatFlow();
168 mdsalManager.installFlow(flowEntity);
171 public void removeDefNATRouteInDPN(BigInteger dpnId, long vpnId, TypedReadWriteTransaction<Configuration> confTx)
172 throws ExecutionException, InterruptedException {
173 FlowEntity flowEntity = buildDefNATFlowEntity(dpnId, vpnId);
174 if (flowEntity == null) {
175 LOG.error("removeDefNATRouteInDPN : Flow entity received is NULL."
176 + "Cannot proceed with installation of Default NAT flow");
179 natServiceCounters.removeDefaultNatFlow();
180 mdsalManager.removeFlow(confTx, flowEntity);
183 public void removeDefNATRouteInDPN(BigInteger dpnId, long bgpVpnId, long routerId,
184 TypedReadWriteTransaction<Configuration> confTx) throws ExecutionException, InterruptedException {
185 FlowEntity flowEntity = buildDefNATFlowEntity(dpnId, bgpVpnId, routerId);
186 if (flowEntity == null) {
187 LOG.error("removeDefNATRouteInDPN : Flow entity received is NULL."
188 + "Cannot proceed with installation of Default NAT flow");
191 natServiceCounters.removeDefaultNatFlow();
192 mdsalManager.removeFlow(confTx, flowEntity);
195 public void addOrDelDefaultFibRouteToSNATForSubnet(Subnets subnet, String networkId, int flowAction, long vpnId) {
196 String providerNet = NatUtil.getElanInstancePhysicalNetwok(networkId, dataBroker);
197 Set<BigInteger> dpnList = natSwitchCache.getSwitchesConnectedToExternal(providerNet);
199 for (BigInteger dpn : dpnList) {
200 addOrDelDefaultFibRouteToSNATForSubnetInDpn(subnet, networkId, flowAction, vpnId, dpn);
204 public void addOrDelDefaultFibRouteToSNATForSubnetInDpn(Subnets subnet, String networkId, int flowAction,
205 long vpnId, BigInteger dpn) {
206 String subnetId = subnet.getId().getValue();
207 String macAddress = NatUtil.getSubnetGwMac(dataBroker, subnet.getId(), networkId);
208 extNetGroupInstaller.installExtNetGroupEntry(new Uuid(networkId), subnet.getId(),
210 FlowEntity flowEntity = NatUtil.buildDefaultNATFlowEntityForExternalSubnet(dpn,
211 vpnId, subnetId, idManager);
212 if (flowAction == NwConstants.ADD_FLOW || flowAction == NwConstants.MOD_FLOW) {
213 LOG.info("addOrDelDefaultFibRouteToSNATForSubnet : Installing flow {} for subnetId {},"
214 + "vpnId {} on dpn {}", flowEntity, subnetId, vpnId, dpn);
215 jobCoordinator.enqueueJob(NatUtil.getDefaultFibRouteToSNATForSubnetJobKey(subnetId, dpn),
216 () -> Collections.singletonList(mdsalManager.installFlow(flowEntity)));
218 LOG.info("addOrDelDefaultFibRouteToSNATForSubnet : Removing flow for subnetId {},"
219 + "vpnId {} with dpn {}", subnetId, vpnId, dpn);
220 jobCoordinator.enqueueJob(NatUtil.getDefaultFibRouteToSNATForSubnetJobKey(subnetId, dpn),
221 () -> Collections.singletonList(mdsalManager.removeFlow(flowEntity)));