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