6e7dbf4cca53f413180c6ff96985fe6cf4a151bf
[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.mappers.NeutronTenantToVniMapper;
19 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.util.ConfigManagerHelper;
20 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General;
21 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518.gpe.feature.data.grouping.GpeFeatureData;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.Lisp;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.dp.subtable.grouping.local.mappings.LocalMapping;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.dp.subtable.grouping.local.mappings.local.mapping.Eid;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.eid.table.grouping.eid.table.VniTable;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.lisp.feature.data.grouping.LispFeatureData;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.locator.sets.grouping.locator.sets.LocatorSet;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.map.register.grouping.MapRegister;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.map.resolvers.grouping.map.resolvers.MapResolver;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.map.servers.grouping.map.servers.MapServer;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 import javax.annotation.Nonnull;
38 import java.util.HashMap;
39 import java.util.concurrent.ExecutionException;
40
41 /**
42  * Created by Shakib Ahmed on 3/29/17.
43  */
44 public class LispStateManager {
45     private static final Logger LOG = LoggerFactory.getLogger(LispStateManager.class);
46
47     private HashMap<String, LispState> lispStateMapper;
48     private MountedDataBrokerProvider mountedDataBrokerProvider;
49     private ConfigManagerHelper lispStateHelper;
50
51     private NeutronTenantToVniMapper neutronTenantToVniMapper;
52
53     private static final short DEFAULT_PRIORITY = 1;
54     private static final short DEFAULT_WEIGHT = 1;
55     public static final String DEFAULT_XTR_KEY = "admin";
56     public static final String DEFAULT_LOCATOR_SET_NAME_PREFIX = "LS";
57     public static final String DEFAULT_MAPPINGRECORD_NAME_PREFIX = "MR";
58
59     public LispStateManager(@Nonnull MountedDataBrokerProvider mountedDataBrokerProvider) {
60         Preconditions.checkNotNull(mountedDataBrokerProvider,
61                 "MountedDataBrokerProvider found to be null!");
62         lispStateMapper = new HashMap<>();
63         this.mountedDataBrokerProvider= mountedDataBrokerProvider;
64         this.lispStateHelper = new ConfigManagerHelper(this.mountedDataBrokerProvider);
65         neutronTenantToVniMapper = NeutronTenantToVniMapper.getInstance();
66     }
67
68     public synchronized void configureEndPoint(AddressEndpointWithLocation addressEp) {
69         try {
70             DataBroker dataBroker = lispStateHelper.getPotentialExternalDataBroker(addressEp).get();
71             String hostName = lispStateHelper.getHostName(addressEp).get();
72             LispState lispStateOfNode = configureHostIfNeeded(hostName, dataBroker);
73
74             long vni = getVni(addressEp.getTenant().getValue());
75             long vrf = vni;
76             addVniToVrfMappingIfNeeded(dataBroker, lispStateOfNode, vni, vrf);
77
78             Eid eid = lispStateHelper.getEid(addressEp, vni);
79
80             if(!lispStateOfNode.eidSetContains(eid)) {
81                 addEidInEidTable(dataBroker, lispStateOfNode, eid);
82             }
83
84         } catch (LispConfigCommandFailedException e) {
85             LOG.warn("Lisp endpoint configuration failed for address endpoint: {}", addressEp);
86         }
87     }
88
89     public synchronized LispState configureHostIfNeeded(String hostName, DataBroker vppDataBroker) throws LispConfigCommandFailedException {
90         LispState lispStateOfNode = lispStateMapper.get(hostName);
91
92         if (lispStateOfNode == null) {
93             lispStateOfNode = new LispState(hostName);
94             try {
95                 enableLispForNode(vppDataBroker, lispStateOfNode);
96
97                 if (ConfigUtil.getInstance().isL3FlatEnabled()) {
98                     enableGpeForNode(vppDataBroker, lispStateOfNode);
99                 }
100
101                 addLocatorSet(vppDataBroker, lispStateOfNode);
102                 addMapResolver(vppDataBroker, lispStateOfNode);
103                 if (ConfigUtil.getInstance().isLispMapRegisterEnabled()) {
104                     enableMapRegister(vppDataBroker, lispStateOfNode);
105                     addMapServer(vppDataBroker, lispStateOfNode);
106                 }
107                 lispStateMapper.put(hostName, lispStateOfNode);
108             } catch (LispNotFoundException e) {
109                 LOG.warn("Lisp host configuration failed: ", e.getMessage());
110                 throw new LispConfigCommandFailedException("Failed LISP configuration!");
111             }
112         }
113         return lispStateOfNode;
114     }
115
116     public synchronized void deleteLispConfigurationForEndpoint(AddressEndpointWithLocation addressEp) {
117         try {
118             DataBroker vppDataBroker = lispStateHelper.getPotentialExternalDataBroker(addressEp).get();
119             String hostName = lispStateHelper.getHostName(addressEp).get();
120
121             LispState lispState = lispStateMapper.get(hostName);
122
123             if (lispState == null) {
124                 LOG.debug("Endpoint not configured for LISP. EndPoint: {}", addressEp);
125             } else {
126                 long vni = getVni(addressEp.getTenant().getValue());
127                 Eid eid = lispStateHelper.getEid(addressEp, vni);
128
129                 if (lispState.eidSetContains(eid)) {
130                     deleteEidFromEidTable(vppDataBroker, lispState, eid);
131                 }
132
133                 if (lispState.eidCount() == 0) {
134                     deleteLispStatesInEndPoints(vppDataBroker, lispState);
135                 }
136             }
137         } catch (LispConfigCommandFailedException e) {
138             LOG.warn("Lisp command execution failed: {}", e.getMessage());
139         }
140     }
141
142     private void enableLispForNode(DataBroker vppDataBroker, LispState lispState) throws LispConfigCommandFailedException {
143         AbstractLispCommand<Lisp>
144                 lispEnableCommand = LispCommandWrapper.enableLisp();
145         if (LispStateCommandExecutor.executePutCommand(vppDataBroker, lispEnableCommand)) {
146             lispState.setLispEnabled(true);
147         } else {
148             throw new LispConfigCommandFailedException("Lisp Enable Command failed execution!");
149         }
150     }
151
152     private void enableGpeForNode(DataBroker vppDataBroker, LispState lispState) throws LispConfigCommandFailedException {
153         AbstractLispCommand<GpeFeatureData>
154                 gpeEnableCommand = LispCommandWrapper.enableGpe();
155         if (LispStateCommandExecutor.executePutCommand(vppDataBroker, gpeEnableCommand)) {
156             lispState.setGpeEnabled(true);
157         } else {
158             throw new LispConfigCommandFailedException("GPE Enable Command failed execution!");
159         }
160     }
161
162     private void addLocatorSet(DataBroker vppDataBroker, LispState lispState) throws LispNotFoundException, LispConfigCommandFailedException {
163         try {
164             String locatorSetName = lispStateHelper.constructLocatorSetName(lispState.getLocatorCount());
165             String interfaceName = lispStateHelper.readRlocInterface(lispState.getHostName(), vppDataBroker).get();
166             AbstractLispCommand<LocatorSet> addLocatorSetCommand = LispCommandWrapper.addLocatorSet(locatorSetName,
167                     interfaceName, DEFAULT_PRIORITY, DEFAULT_WEIGHT);
168             if (LispStateCommandExecutor.executePutCommand(vppDataBroker, addLocatorSetCommand)) {
169                 lispState.setLocIntfToLocSetNameMapping(interfaceName, locatorSetName);
170             } else {
171                 throw new LispConfigCommandFailedException("Lisp add locator set failed for host "
172                         + lispState.getHostName() + " and locator interface " + interfaceName);
173             }
174         } catch (InterruptedException | ExecutionException e) {
175             throw new LispNotFoundException("No interface with Ip Address found!");
176         }
177
178     }
179
180     private void addMapResolver(DataBroker vppDataBroker, LispState lispState) throws LispConfigCommandFailedException {
181         IpAddress mapResolverIpAddress = ConfigUtil.getInstance().getOdlTenantIp();
182         Preconditions.checkNotNull(mapResolverIpAddress, "Map Resolver ip not properly configured!");
183
184         AbstractLispCommand<MapResolver> addMapResolverCommand = LispCommandWrapper.
185                 addMapResolver(mapResolverIpAddress);
186         if (LispStateCommandExecutor.executePutCommand(vppDataBroker, addMapResolverCommand)) {
187             lispState.addInMapResolverSet(mapResolverIpAddress);
188         } else {
189             throw new LispConfigCommandFailedException("Lisp add map resolver for host " + lispState.getHostName()
190                     + " failed for ODL ip " + mapResolverIpAddress);
191         }
192     }
193
194     private void addMapServer(DataBroker vppDataBroker, LispState lispState) throws LispConfigCommandFailedException {
195         IpAddress mapServerIpAddress = ConfigUtil.getInstance().getOdlTenantIp();
196         Preconditions.checkNotNull(mapServerIpAddress, "Mapserver ip not properly configured!");
197         AbstractLispCommand<MapServer> addMapServerCommand = LispCommandWrapper.addMapServer(mapServerIpAddress);
198
199         if (LispStateCommandExecutor.executePutCommand(vppDataBroker, addMapServerCommand)) {
200             lispState.addInMapServerSet(mapServerIpAddress);
201         } else {
202             throw new LispConfigCommandFailedException("Lisp add map server for host " + lispState.getHostName()
203                     + " failed for ODL ip " + mapServerIpAddress);
204         }
205     }
206
207     private void enableMapRegister(DataBroker vppDataBroker, LispState lispState) throws LispConfigCommandFailedException {
208         AbstractLispCommand<MapRegister> enableMapRegisterCommand = LispCommandWrapper.enableMapRegister();
209
210         if (LispStateCommandExecutor.executePutCommand(vppDataBroker, enableMapRegisterCommand)) {
211             lispState.setMapRegisteredEnabled(true);
212         } else {
213             throw new LispConfigCommandFailedException("Lisp enable mapregistration for host "
214                     + lispState.getHostName() + " failed!");
215         }
216
217     }
218
219     private void addVniToVrfMappingIfNeeded(DataBroker vppDataBroker,
220                                             LispState lispState,
221                                             long vni, long vrf) throws LispConfigCommandFailedException {
222         if (!lispState.vniSetContains(vni)) {
223             AbstractLispCommand<VniTable> addVniToVrfMapping = LispCommandWrapper.mapVniToVrf(vni, vrf);
224             addVniToVrfMapping.setOptions(General.Operations.PUT);
225             if (LispStateCommandExecutor.executePutCommand(vppDataBroker, addVniToVrfMapping)) {
226                 lispState.addInVniSet(vni);
227             } else {
228                 throw new LispConfigCommandFailedException("Lisp add vrf " + vrf +" for vni " +vni
229                         + " command failed!");
230             }
231         }
232     }
233
234     private void addEidInEidTable(DataBroker vppDataBroker,
235                                   LispState lispState,
236                                   Eid eid) throws LispConfigCommandFailedException {
237         String mappingId = lispStateHelper.constructMappingName(lispState.getInterfaceId());
238         AbstractLispCommand<LocalMapping> addLocalMappingInEidTableCommand = LispCommandWrapper
239                 .addLocalMappingInEidTable(mappingId,
240                         eid,
241                         lispStateHelper.getFirstLocatorSetName(lispState),
242                         lispStateHelper.getDefaultHmacKey());
243         if (LispStateCommandExecutor.executePutCommand(vppDataBroker, addLocalMappingInEidTableCommand)) {
244             lispState.addInEidSet(eid, mappingId);
245         } else {
246             throw new LispConfigCommandFailedException("Lisp add local mapping for eid " + eid + "failed!");
247         }
248     }
249
250     private void deleteLispStatesInEndPoints(DataBroker vppDataBroker,
251                                              LispState lispState) throws LispConfigCommandFailedException {
252         AbstractLispCommand<LispFeatureData> deleteLispFeatureData = LispCommandWrapper.deleteLispFeatureData();
253
254         if (LispStateCommandExecutor.executeDeleteCommand(vppDataBroker, deleteLispFeatureData)) {
255             String computeNode = lispState.getHostName();
256             lispStateMapper.remove(computeNode);
257         } else {
258             throw new LispConfigCommandFailedException("Lisp delete feature data command failed!");
259         }
260     }
261
262     private void deleteEidFromEidTable(DataBroker vppDataBroker,
263                                        LispState lispState,
264                                        Eid eid) throws LispConfigCommandFailedException {
265         String mappingId = lispState.getEidMapping(eid);
266         long value = eid.getVirtualNetworkId().getValue();
267
268         AbstractLispCommand<LocalMapping> deleteLocalMappingCommand = LispCommandWrapper
269                 .deleteLocalMappingFromEidTable(mappingId, value);
270
271         if (LispStateCommandExecutor.executeDeleteCommand(vppDataBroker, deleteLocalMappingCommand)) {
272             lispState.deleteEid(eid);
273         } else {
274             throw new LispConfigCommandFailedException("Lisp delete local mapping command failed!");
275         }
276     }
277
278     private long getVni(String tenantUuid) {
279         return neutronTenantToVniMapper.getVni(tenantUuid);
280     }
281 }