Switch to JDT annotations for Nullable and NonNull
[netvirt.git] / natservice / impl / src / main / java / org / opendaylight / netvirt / natservice / internal / SNATDefaultRouteProgrammer.java
1 /*
2  * Copyright © 2016, 2017 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.netvirt.natservice.internal;
9
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;
16 import java.util.Set;
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;
42
43 @Singleton
44 public class SNATDefaultRouteProgrammer {
45
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;
54
55     @Inject
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;
67     }
68
69     @Nullable
70     private FlowEntity buildDefNATFlowEntity(BigInteger dpId, long vpnId) {
71         InetAddress defaultIP = null;
72         try {
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);
77             return null;
78         }
79
80         List<MatchInfo> matches = new ArrayList<>();
81         matches.add(MatchEthernetType.IPV4);
82
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 }));
86
87         //add match for vrfid
88         matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(vpnId), MetaDataUtil.METADATA_MASK_VRFID));
89
90         List<InstructionInfo> instructions = new ArrayList<>();
91         instructions.add(new InstructionGotoTable(NwConstants.PSNAT_TABLE));
92
93         String flowRef = NatUtil.getFlowRef(dpId, NwConstants.L3_FIB_TABLE, defaultIP, vpnId);
94
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);
98
99         return flowEntity;
100     }
101
102     @Nullable
103     private FlowEntity buildDefNATFlowEntity(BigInteger dpId, long bgpVpnId, long routerId) {
104         InetAddress defaultIP = null;
105         try {
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);
110             return null;
111         }
112
113         List<MatchInfo> matches = new ArrayList<>();
114         matches.add(MatchEthernetType.IPV4);
115
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 }));
119
120         //add match for vrfid
121         matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(bgpVpnId), MetaDataUtil.METADATA_MASK_VRFID));
122
123         List<InstructionInfo> instructions = new ArrayList<>();
124         instructions.add(new InstructionGotoTable(NwConstants.PSNAT_TABLE));
125
126         String flowRef = NatUtil.getFlowRef(dpId, NwConstants.L3_FIB_TABLE, defaultIP, routerId);
127
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);
131
132         return flowEntity;
133
134
135     }
136
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");
142             return;
143         }
144         natServiceCounters.installDefaultNatFlow();
145         mdsalManager.addFlow(confTx, flowEntity);
146     }
147
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");
154             return;
155         }
156         natServiceCounters.installDefaultNatFlow();
157         mdsalManager.addFlow(confTx, flowEntity);
158     }
159
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");
165             return;
166         }
167         natServiceCounters.installDefaultNatFlow();
168         mdsalManager.installFlow(flowEntity);
169     }
170
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");
177             return;
178         }
179         natServiceCounters.removeDefaultNatFlow();
180         mdsalManager.removeFlow(confTx, flowEntity);
181     }
182
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");
189             return;
190         }
191         natServiceCounters.removeDefaultNatFlow();
192         mdsalManager.removeFlow(confTx, flowEntity);
193     }
194
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);
198
199         for (BigInteger dpn : dpnList) {
200             addOrDelDefaultFibRouteToSNATForSubnetInDpn(subnet, networkId, flowAction, vpnId, dpn);
201         }
202     }
203
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(),
209                 dpn, macAddress);
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)));
217         } else {
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)));
222         }
223     }
224 }