Add implementation for GPE native forwarding
[groupbasedpolicy.git] / renderers / vpp / src / main / java / org / opendaylight / groupbasedpolicy / renderer / vpp / lisp / LispStateManager.java
1 /*
2  * Copyright (c) 2017 Cisco Systems. 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
9 package org.opendaylight.groupbasedpolicy.renderer.vpp.lisp;
10
11 import com.google.common.base.Preconditions;
12 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
13 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.lisp.AbstractLispCommand;
14 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.lisp.LispCommandWrapper;
15 import org.opendaylight.groupbasedpolicy.renderer.vpp.config.ConfigUtil;
16 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.exception.LispConfigCommandFailedException;
17 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.exception.LispNotFoundException;
18 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.EndpointHost;
19 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.HostRelatedInfoContainer;
20 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.LispState;
21 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.NeutronTenantToVniMapper;
22 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.util.ConfigManagerHelper;
23 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.util.Constants;
24 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General;
25 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518.gpe.feature.data.grouping.GpeFeatureData;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518.NativeForwardPathsTables;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518._native.forward.paths.tables._native.forward.paths.table.NativeForwardPath;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.Lisp;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.dp.subtable.grouping.local.mappings.LocalMapping;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.dp.subtable.grouping.local.mappings.local.mapping.Eid;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.eid.table.grouping.eid.table.VniTable;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.itr.remote.locator.sets.grouping.ItrRemoteLocatorSet;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.lisp.feature.data.grouping.LispFeatureData;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.locator.sets.grouping.locator.sets.LocatorSet;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.map.register.grouping.MapRegister;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.map.resolvers.grouping.map.resolvers.MapResolver;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.map.servers.grouping.map.servers.MapServer;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43
44 import javax.annotation.Nonnull;
45 import java.util.concurrent.ExecutionException;
46
47 /**
48  * Created by Shakib Ahmed on 3/29/17.
49  */
50 public class LispStateManager {
51     private static final Logger LOG = LoggerFactory.getLogger(LispStateManager.class);
52
53     private HostRelatedInfoContainer hostRelatedInfoContainer;
54     private MountedDataBrokerProvider mountedDataBrokerProvider;
55     private ConfigManagerHelper lispStateHelper;
56
57     private NeutronTenantToVniMapper neutronTenantToVniMapper;
58
59     private static final short DEFAULT_PRIORITY = 1;
60     private static final short DEFAULT_WEIGHT = 1;
61     public static final String DEFAULT_XTR_KEY = "admin";
62     public static final String DEFAULT_LOCATOR_SET_NAME_PREFIX = "LS";
63     public static final String DEFAULT_MAPPINGRECORD_NAME_PREFIX = "MR_";
64
65     public LispStateManager(@Nonnull MountedDataBrokerProvider mountedDataBrokerProvider) {
66         Preconditions.checkNotNull(mountedDataBrokerProvider,
67                 "MountedDataBrokerProvider found to be null!");
68         hostRelatedInfoContainer = HostRelatedInfoContainer.getInstance();
69         this.mountedDataBrokerProvider= mountedDataBrokerProvider;
70         this.lispStateHelper = new ConfigManagerHelper(this.mountedDataBrokerProvider);
71         neutronTenantToVniMapper = NeutronTenantToVniMapper.getInstance();
72     }
73
74     public synchronized void processCreateEndPoint(AddressEndpointWithLocation addressEp) {
75         try {
76             if (lispStateHelper.isMetadataPort(addressEp)) {
77                 return;
78             }
79             EndpointHost endpointHost = lispStateHelper.getEndpointHostInformation(addressEp);
80             LispState lispStateOfHost = configureHostIfNeeded(endpointHost);
81
82             long vni = getVni(addressEp.getTenant().getValue());
83             long vrf = vni;
84
85             Eid eid = lispStateHelper.getEid(addressEp, vni);
86             String eidMappingName = lispStateHelper.constructEidMappingName(addressEp);
87
88             addVniToVrfMappingIfNeeded(endpointHost.getHostDataBroker(), lispStateOfHost, vni, vrf);
89
90             if (lispStateHelper.getInterfaceIp(addressEp).getValue().equals(Constants.METADATA_IP)) {
91                 return;
92             }
93
94             addEidOnHostIfNeeded(endpointHost, lispStateOfHost, eid, eidMappingName);
95         } catch (LispConfigCommandFailedException e) {
96             LOG.warn("Lisp endpoint configuration failed for address endpoint: {}", addressEp);
97         }
98     }
99
100     private void addEidOnHostIfNeeded(EndpointHost endpointHost, LispState lispStateOfNode, Eid eid,
101                                       String eidMappingName)
102             throws LispConfigCommandFailedException {
103         if(!lispStateOfNode.eidSetContains(eid)) {
104             addEidInEidTable(endpointHost.getHostDataBroker(), lispStateOfNode, eid, eidMappingName);
105         }
106     }
107
108     private synchronized LispState configureHostIfNeeded(EndpointHost endpointHost)
109             throws LispConfigCommandFailedException {
110         LispState lispStateOfHost = hostRelatedInfoContainer.getLispStateOfHost(endpointHost.getHostName());
111
112         if (lispStateOfHost == null) {
113             LOG.debug("Configuring host {} for LISP", endpointHost.getHostName());
114             lispStateOfHost = new LispState();
115             try {
116                 enableLispOnHost(endpointHost, lispStateOfHost);
117                 enableGpeOnHostIfNeeded(endpointHost, lispStateOfHost);
118                 addLocatorSetOnHost(endpointHost, lispStateOfHost);
119                 addMapResolverOnHost(endpointHost, lispStateOfHost);
120                 enableMapRegistrationOnHostIfNeeded(endpointHost, lispStateOfHost);
121
122                 hostRelatedInfoContainer.setLispStateOfHost(endpointHost.getHostName(), lispStateOfHost);
123             } catch (LispNotFoundException e) {
124                 LOG.warn("Lisp host configuration failed: ", e.getMessage());
125                 throw new LispConfigCommandFailedException("Failed LISP configuration!");
126             }
127         }
128         return lispStateOfHost;
129     }
130
131     private void enableGpeOnHostIfNeeded(EndpointHost endpointHost, LispState lispStateOfHost)
132             throws LispConfigCommandFailedException {
133         if (ConfigUtil.getInstance().isL3FlatEnabled()) {
134             enableGpeForHost(endpointHost, lispStateOfHost);
135         }
136     }
137
138     private void enableMapRegistrationOnHostIfNeeded(EndpointHost endpointHost, LispState lispStateOfHost)
139             throws LispConfigCommandFailedException {
140         if (ConfigUtil.getInstance().isLispMapRegisterEnabled()) {
141             enableMapRegister(endpointHost);
142             addMapServer(endpointHost, lispStateOfHost);
143         }
144     }
145
146     private void enableLispOnHost(EndpointHost endpointHost, LispState lispState)
147             throws LispConfigCommandFailedException {
148         AbstractLispCommand<Lisp>
149                 lispEnableCommand = LispCommandWrapper.enableLisp();
150         if (LispStateCommandExecutor.executePutCommand(endpointHost.getHostDataBroker(), lispEnableCommand)) {
151             lispState.setLispEnabled(true);
152         } else {
153             throw new LispConfigCommandFailedException("Lisp Enable Command failed execution!");
154         }
155     }
156
157     private void enableGpeForHost(EndpointHost endpointHost, LispState lispState)
158             throws LispConfigCommandFailedException {
159         AbstractLispCommand<GpeFeatureData>
160                 gpeEnableCommand = LispCommandWrapper.enableGpe();
161         if (LispStateCommandExecutor.executePutCommand(endpointHost.getHostDataBroker(), gpeEnableCommand)) {
162             lispState.setGpeEnabled(true);
163         } else {
164             throw new LispConfigCommandFailedException("GPE Enable Command failed execution!");
165         }
166     }
167
168     private void addLocatorSetOnHost(EndpointHost endpointHost, LispState lispState)
169             throws LispNotFoundException, LispConfigCommandFailedException {
170         try {
171             String locatorSetName = lispStateHelper.constructLocatorSetName(lispState.getLocatorCount());
172             String lispDataInterfaceName = lispStateHelper
173                     .getLispDataRlocInterfaceName(endpointHost.getHostName(), endpointHost.getHostDataBroker()).get();
174             AbstractLispCommand<LocatorSet> addLocatorSetCommand = LispCommandWrapper.addLocatorSet(locatorSetName,
175                     lispDataInterfaceName, DEFAULT_PRIORITY, DEFAULT_WEIGHT);
176             if (LispStateCommandExecutor.executePutCommand(endpointHost.getHostDataBroker(), addLocatorSetCommand)) {
177                 lispState.setLocIntfToLocSetNameMapping(lispDataInterfaceName, locatorSetName);
178             } else {
179                 throw new LispConfigCommandFailedException("Lisp add locator set failed for host "
180                         + endpointHost.getHostName() + " and locator interface " + lispDataInterfaceName);
181             }
182
183             addExtraItrRlocLocatorSetIfNeeded(endpointHost, lispDataInterfaceName);
184         } catch (InterruptedException | ExecutionException e) {
185             throw new LispNotFoundException("No interface with Ip Address found!");
186         }
187     }
188
189     private void addExtraItrRlocLocatorSetIfNeeded(EndpointHost endpointHost, String lispDataInterfaceName)
190             throws LispNotFoundException, LispConfigCommandFailedException {
191         String lispCpRlocInterfaceName = lispStateHelper.getLispCpRlocInterfaceName(endpointHost.getHostDataBroker());
192         if (lispCpRlocInterfaceName == null
193                 || lispCpRlocInterfaceName.isEmpty()
194                 || lispCpRlocInterfaceName.equals(lispDataInterfaceName)) {
195             return;
196         }
197
198         addItrLocatorSet(endpointHost, lispCpRlocInterfaceName);
199     }
200
201     private void addItrLocatorSet(EndpointHost endpointHost, String lispCpInterfaceName)
202             throws LispNotFoundException, LispConfigCommandFailedException {
203         String locatorSetName = lispStateHelper.constructLocatorSetNameForItrRloc();
204         AbstractLispCommand<LocatorSet> addLocatorSetCommand = LispCommandWrapper.addLocatorSet(locatorSetName,
205                 lispCpInterfaceName, DEFAULT_PRIORITY, DEFAULT_WEIGHT);
206         if (!LispStateCommandExecutor.executePutCommand(endpointHost.getHostDataBroker(), addLocatorSetCommand)) {
207             throw new LispConfigCommandFailedException("Lisp add locator set failed for host "
208                     + endpointHost.getHostName() + " and locator interface " + lispCpInterfaceName);
209         }
210
211         AbstractLispCommand<ItrRemoteLocatorSet> addItrRlocCommand = LispCommandWrapper.addItrRloc(locatorSetName);
212         if (!LispStateCommandExecutor.executePutCommand(endpointHost.getHostDataBroker(), addItrRlocCommand)) {
213             throw new LispConfigCommandFailedException("Lisp add Itr Rloc command failed for host "
214                     + endpointHost.getHostName() + " and locator set " + locatorSetName);
215         }
216     }
217
218     private void addMapResolverOnHost(EndpointHost endpointHost, LispState lispState)
219             throws LispConfigCommandFailedException {
220         IpAddress mapResolverIpAddress = ConfigUtil.getInstance().getOdlIp();
221         Preconditions.checkNotNull(mapResolverIpAddress, "Map Resolver ip not properly configured!");
222
223         AbstractLispCommand<MapResolver> addMapResolverCommand = LispCommandWrapper.
224                 addMapResolver(mapResolverIpAddress);
225         if (LispStateCommandExecutor.executePutCommand(endpointHost.getHostDataBroker(), addMapResolverCommand)) {
226             lispState.addInMapResolverSet(mapResolverIpAddress);
227         } else {
228             throw new LispConfigCommandFailedException("Lisp add map resolver for host " + endpointHost.getHostName()
229                     + " failed for ODL ip " + mapResolverIpAddress);
230         }
231     }
232
233     private void enableMapRegister(EndpointHost endpointHost)
234             throws LispConfigCommandFailedException {
235         AbstractLispCommand<MapRegister> enableMapRegisterCommand = LispCommandWrapper.enableMapRegister();
236
237         if (LispStateCommandExecutor.executePutCommand(endpointHost.getHostDataBroker(), enableMapRegisterCommand)) {
238         } else {
239             throw new LispConfigCommandFailedException("Lisp enable mapregistration for host "
240                     + endpointHost.getHostName() + " failed!");
241         }
242
243     }
244
245     private void addMapServer(EndpointHost endpointHost, LispState lispState) throws LispConfigCommandFailedException {
246         IpAddress mapServerIpAddress = ConfigUtil.getInstance().getOdlIp();
247         Preconditions.checkNotNull(mapServerIpAddress, "Mapserver ip not properly configured!");
248         AbstractLispCommand<MapServer> addMapServerCommand = LispCommandWrapper.addMapServer(mapServerIpAddress);
249
250         if (LispStateCommandExecutor.executePutCommand(endpointHost.getHostDataBroker(), addMapServerCommand)) {
251             lispState.addInMapServerSet(mapServerIpAddress);
252         } else {
253             throw new LispConfigCommandFailedException("Lisp add map server for host " + endpointHost.getHostName()
254                     + " failed for ODL ip " + mapServerIpAddress);
255         }
256     }
257
258     private void addVniToVrfMappingIfNeeded(DataBroker vppDataBroker,
259                                             LispState lispState,
260                                             long vni, long vrf) throws LispConfigCommandFailedException {
261         if (!lispState.isVniConfigured(vni)) {
262             AbstractLispCommand<VniTable> addVniToVrfMapping = LispCommandWrapper.mapVniToVrf(vni, vrf);
263             addVniToVrfMapping.setOptions(General.Operations.PUT);
264             if (LispStateCommandExecutor.executePutCommand(vppDataBroker, addVniToVrfMapping)) {
265                 lispState.addInVniSet(vni);
266             } else {
267                 throw new LispConfigCommandFailedException("Lisp add vrf " + vrf +" for vni " +vni
268                         + " command failed!");
269             }
270         }
271     }
272
273     private void addNativeForwardPath(EndpointHost endpointHost, long vrf, IpAddress nativeForwardIp)
274             throws LispConfigCommandFailedException {
275
276         AbstractLispCommand<NativeForwardPath> lispCommand =
277                 LispCommandWrapper.addNativeForwardEntry(vrf, nativeForwardIp);
278         if (LispStateCommandExecutor.executePutCommand(endpointHost.getHostDataBroker(), lispCommand)) {
279             LOG.debug("Added {} as native forwarding IP");
280         } else {
281             throw new LispConfigCommandFailedException("Lisp add Native forward failed for VNI " + vrf);
282         }
283     }
284
285     private void addEidInEidTable(DataBroker vppDataBroker,
286                                   LispState lispState,
287                                   Eid eid,
288                                   String eidMappingName) throws LispConfigCommandFailedException {
289         AbstractLispCommand<LocalMapping> addLocalMappingInEidTableCommand = LispCommandWrapper
290                 .addLocalMappingInEidTable(eidMappingName,
291                         eid,
292                         lispStateHelper.getFirstLocatorSetName(lispState),
293                         lispStateHelper.getDefaultHmacKey());
294         if (LispStateCommandExecutor.executePutCommand(vppDataBroker, addLocalMappingInEidTableCommand)) {
295             lispState.addEidInEidSet(eid);
296         } else {
297             throw new LispConfigCommandFailedException("Lisp add local mapping for eid " + eid + "failed!");
298         }
299     }
300
301     public synchronized void processDeleteEndpoint(AddressEndpointWithLocation addressEp) {
302         try {
303
304             if (lispStateHelper.isMetadataPort(addressEp)) {
305                 return;
306             }
307
308             EndpointHost endpointHost = lispStateHelper.getEndpointHostInformation(addressEp);
309
310             LispState lispState = hostRelatedInfoContainer.getLispStateOfHost(endpointHost.getHostName());
311
312             if (lispState == null) {
313                 LOG.debug("Endpoint not configured for LISP. EndPoint: {}", addressEp);
314             } else {
315                 long vni = getVni(addressEp.getTenant().getValue());
316                 Eid eid = lispStateHelper.getEid(addressEp, vni);
317                 String eidMappingName = lispStateHelper.constructEidMappingName(addressEp);
318
319                 deleteEidFromLocalEidTableOfHostIfNeeded(endpointHost, lispState, eid, eidMappingName);
320
321                 if (lispState.eidCount() == 0) {
322                     deleteLispStatesFromHost(endpointHost);
323                     deleteNativeForwardPathsTables(endpointHost);
324                 }
325             }
326         } catch (LispConfigCommandFailedException e) {
327             LOG.warn("Lisp command execution failed: {}", e.getMessage());
328         }
329     }
330
331     private void deleteEidFromLocalEidTableOfHostIfNeeded(EndpointHost endpointHost, LispState lispState, Eid eid, String eidMappingName) throws LispConfigCommandFailedException {
332         if (lispState.eidSetContains(eid)) {
333             deleteEidFromLocalEidTableOfHost(endpointHost, lispState, eid, eidMappingName);
334         }
335     }
336
337     private void deleteEidFromLocalEidTableOfHost(EndpointHost endpointHost,
338                                        LispState lispState,
339                                        Eid eid,
340                                        String eidMappingName) throws LispConfigCommandFailedException {
341         long value = eid.getVirtualNetworkId().getValue();
342
343         AbstractLispCommand<LocalMapping> deleteLocalMappingCommand = LispCommandWrapper
344                 .deleteLocalMappingFromEidTable(eidMappingName, value);
345
346         if (LispStateCommandExecutor
347                 .executeDeleteCommand(endpointHost.getHostDataBroker(), deleteLocalMappingCommand)) {
348             LOG.debug("Successfully deleted eid {} from host {}", eid, endpointHost.getHostName());
349             lispState.deleteEid(eid);
350         } else {
351             throw new LispConfigCommandFailedException("Lisp delete local mapping command failed!");
352         }
353     }
354
355
356     private void deleteLispStatesFromHost(EndpointHost endpointHost) throws LispConfigCommandFailedException {
357         AbstractLispCommand<LispFeatureData> deleteLispFeatureData = LispCommandWrapper.deleteLispFeatureData();
358
359         if (LispStateCommandExecutor.executeDeleteCommand(endpointHost.getHostDataBroker(), deleteLispFeatureData)) {
360             hostRelatedInfoContainer.deleteLispStateOfHost(endpointHost.getHostName());
361             LOG.debug("Deleted all lisp data for host {}", endpointHost.getHostName());
362         } else {
363             throw new LispConfigCommandFailedException("Lisp delete feature data command failed!");
364         }
365     }
366
367     private void deleteNativeForwardPathsTables(EndpointHost endpointHost)
368             throws LispConfigCommandFailedException {
369         AbstractLispCommand<NativeForwardPathsTables> deleteNativeForwardPathsTables = LispCommandWrapper
370                 .deleteNativeForwardPathsTables();
371
372         if (!LispStateCommandExecutor.executeDeleteCommand(endpointHost.getHostDataBroker(),
373                 deleteNativeForwardPathsTables)) {
374             throw new LispConfigCommandFailedException("Delete Native Forward Paths Tables command failed!");
375         }
376     }
377
378     private long getVni(String tenantUuid) {
379         return neutronTenantToVniMapper.getVni(tenantUuid);
380     }
381 }