2 * Copyright (c) 2017 Cisco Systems. 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
9 package org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.loopback;
11 import javax.annotation.Nonnull;
13 import org.apache.commons.lang3.tuple.Pair;
14 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.LoopbackCommand;
15 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.LoopbackCommandWrapper;
16 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.ProxyRangeCommand;
17 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.lisp.AbstractLispCommand;
18 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.lisp.LispCommandWrapper;
19 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.LispStateCommandExecutor;
20 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.exception.LispConfigCommandFailedException;
21 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.exception.LispHelperArgumentException;
22 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.EndpointHost;
23 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.HostRelatedInfoContainer;
24 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.SubnetState;
25 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.VrfHolder;
26 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.NeutronTenantToVniMapper;
27 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.SubnetUuidToGbpSubnetMapper;
28 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.util.ConfigManagerHelper;
29 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.util.Constants;
30 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.util.IpAddressUtil;
31 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.GbpNetconfTransaction;
32 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General;
33 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.LispUtil;
34 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;
35 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.Ipv4PrefixAfi;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCase;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.GbpSubnet;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518.gpe.entry.table.grouping.gpe.entry.table.GpeEntry;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518.gpe.entry.table.grouping.gpe.entry.table.gpe.entry.RemoteEid;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.unnumbered.interfaces.rev170510.InterfaceUnnumberedAugmentation;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.unnumbered.interfaces.rev170510.InterfaceUnnumberedAugmentationBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.unnumbered.interfaces.rev170510.unnumbered.config.attributes.UnnumberedBuilder;
50 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
51 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
52 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
56 import com.google.common.base.Preconditions;
59 * Created by Shakib Ahmed on 4/26/17.
61 public class LoopbackManager {
62 private static final Logger LOG = LoggerFactory.getLogger(LoopbackManager.class);
64 private ConfigManagerHelper loopbackManagerHelper;
66 private HostRelatedInfoContainer hostRelatedInfoContainer = HostRelatedInfoContainer.getInstance();
67 private SubnetUuidToGbpSubnetMapper subnetUuidToGbpSubnetMapper = SubnetUuidToGbpSubnetMapper.getInstance();
68 private NeutronTenantToVniMapper neutronTenantToVniMapper = NeutronTenantToVniMapper.getInstance();
70 public LoopbackManager(@Nonnull MountedDataBrokerProvider mountedDataBrokerProvider) {
71 this.loopbackManagerHelper = new ConfigManagerHelper(mountedDataBrokerProvider);
74 public void createBviLoopbackIfNeeded(AddressEndpointWithLocation addressEp,
75 String bridgeDomainName) {
77 EndpointHost endpointHost = loopbackManagerHelper.getEndpointHostInformation(addressEp);
78 long vni = getVni(addressEp.getTenant().getValue());
80 String subnetUuid = loopbackManagerHelper.getSubnet(addressEp);
82 VrfHolder hostVrfHolder = hostRelatedInfoContainer.getVrfStateOfHost(endpointHost.getHostName());
84 if (!hostVrfHolder.hasVrf(vrfId)) {
85 //dummy init for bridge domain case
86 hostVrfHolder.initializeVrfState(vrfId, Constants.DUMMY_PROTOCOL_BRIDGE_DOMAIN);
89 SubnetState subnetState = hostVrfHolder.getVrfState(vni)
91 .getSubnetState(subnetUuid);
93 if (!subnetState.isGwConfigured()) {
97 GbpSubnet gbpSubnetInfo = Preconditions.checkNotNull(getSubnetInfo(subnetUuid),
98 "Subnet UUID {} hasn't been created yet!", subnetUuid);
100 String gwInterfaceName = loopbackManagerHelper.getGatewayInterfaceName(Constants.GW_NAME_PREFIX, subnetUuid);
102 LoopbackCommand bviLoopbackCommand = LoopbackCommandWrapper
103 .bviLoopbackPutCommand(gwInterfaceName, vni, gbpSubnetInfo.getGatewayIp(), gbpSubnetInfo.getCidr(),
105 createLoopbackInterface(endpointHost.getHostName(), subnetState, bviLoopbackCommand);
106 } catch (LispConfigCommandFailedException e) {
107 LOG.warn("LISP couldn't be configured: {}", e.getMessage());
111 public void createSimpleLoopbackIfNeeded(AddressEndpointWithLocation addressEp) {
114 if (loopbackManagerHelper.isMetadataPort(addressEp)) {
117 String hostName = loopbackManagerHelper.getHostName(addressEp).get();
118 long vni = getVni(addressEp.getTenant().getValue());
120 String subnetUuid = loopbackManagerHelper.getSubnet(addressEp);
122 SubnetState stateOfSubnetUuid = hostRelatedInfoContainer
123 .getVrfStateOfHost(hostName)
124 .getVrfState(vrfId).getSubnetHolder()
125 .getSubnetState(subnetUuid);
127 GbpSubnet gbpSubnetInfo = Preconditions.checkNotNull(getSubnetInfo(subnetUuid),
128 "Subnet UUID {} hasn't been created yet!", subnetUuid);
130 if (!stateOfSubnetUuid.isGwConfigured()) {
131 String interfaceName = loopbackManagerHelper.getGatewayInterfaceName(Constants.GW_NAME_PREFIX,
133 LoopbackCommand simpleLoopbackCommand = LoopbackCommandWrapper
134 .simpleLoopbackPutCommand(interfaceName, vrfId, gbpSubnetInfo.getGatewayIp(),
135 gbpSubnetInfo.getCidr());
136 createLoopbackInterface(hostName, stateOfSubnetUuid, simpleLoopbackCommand);
137 addProxyArpRange(hostName, vrfId, gbpSubnetInfo);
138 addGpeEntry(VppIidFactory.getNetconfNodeIid(new NodeId(hostName)), gbpSubnetInfo, vni);
141 String gwInterfaceName = stateOfSubnetUuid.getGwInterfaceName();
142 addUnnumberedInterface(addressEp, gwInterfaceName);
143 } catch (LispConfigCommandFailedException e) {
144 LOG.warn("LISP couldn't be configured: {}", e.getMessage());
148 private void createLoopbackInterface(String hostName,
149 SubnetState subnetState,
150 LoopbackCommand loopbackCommand) throws LispConfigCommandFailedException {
152 if (GbpNetconfTransaction.netconfSyncedWrite(VppIidFactory.getNetconfNodeIid(new NodeId(hostName)),
153 loopbackCommand, GbpNetconfTransaction.RETRY_COUNT)) {
154 subnetState.setGwInterfaceName(loopbackCommand.getName());
156 throw new LispConfigCommandFailedException("BVI could not be created for "
157 + hostName + " and bridge domain " + loopbackCommand.getBridgeDomain());
161 public void handleEndpointDelete(AddressEndpointWithLocation addressEp) {
163 if (loopbackManagerHelper.isMetadataPort(addressEp)) {
166 String hostName = loopbackManagerHelper.getHostName(addressEp).get();
167 String portSubnetUuid = loopbackManagerHelper.getSubnet(addressEp);
168 long vrfId = getVni(addressEp.getTenant().getValue());
169 SubnetState subnetStateForSubnetUuid = hostRelatedInfoContainer
170 .getVrfStateOfHost(hostName)
173 .getSubnetState(portSubnetUuid);
175 if (!subnetStateForSubnetUuid.hasIpsInSubnet()) {
176 String gwInterfaceName = subnetStateForSubnetUuid.getGwInterfaceName();
177 GbpSubnet gbpSubnetInfo = Preconditions.checkNotNull(subnetUuidToGbpSubnetMapper.getSubnetInfo(portSubnetUuid),
179 long vni = getVni(addressEp.getTenant().getValue());
181 InstanceIdentifier<Node> iid = VppIidFactory.getNetconfNodeIid(new NodeId(hostName));
182 deleteSpecificLoopback(iid, gwInterfaceName);
183 deleteProxyArpRange(hostName, vni, gbpSubnetInfo);
184 deleteGpeEntry(iid, Constants.GPE_ENTRY_PREFIX + gbpSubnetInfo.getId() + "_1");
185 deleteGpeEntry(iid, Constants.GPE_ENTRY_PREFIX + gbpSubnetInfo.getId() + "_2");
186 hostRelatedInfoContainer.getVrfStateOfHost(hostName)
189 .removeSubnetState(portSubnetUuid);
190 } catch (LispConfigCommandFailedException e) {
191 LOG.warn("Loopback not deleted properly: {}", e.getMessage());
196 private void deleteSpecificLoopback(InstanceIdentifier<Node> nodeIid, String interfaceName) throws LispConfigCommandFailedException {
197 if (!GbpNetconfTransaction.netconfSyncedDelete(nodeIid,
198 VppIidFactory.getInterfaceIID(new InterfaceKey(interfaceName)), GbpNetconfTransaction.RETRY_COUNT)) {
199 throw new LispConfigCommandFailedException("Failed to delete Loopback interface!");
201 LOG.debug("Deleted loopback interface!");
205 private void addProxyArpRange(String hostName,
207 GbpSubnet gbpSubnetInfo) throws LispConfigCommandFailedException {
208 Ipv4Prefix subnetPrefix = gbpSubnetInfo.getCidr().getIpv4Prefix();
210 Preconditions.checkNotNull(subnetPrefix, "Subnet CIDR found to be null for "
211 + "subnet uuid =" + gbpSubnetInfo.getId() + "!");
213 Pair<Ipv4Address, Ipv4Address> startAndEndAddress = IpAddressUtil.getStartAndEndIp(subnetPrefix);
215 if (!putArpRangesCommand(VppIidFactory.getNetconfNodeIid(new NodeId(hostName)),
217 startAndEndAddress.getLeft(),
218 startAndEndAddress.getRight())) {
219 throw new LispConfigCommandFailedException("Proxy arp configuration failed for subnet uuid: " +
220 gbpSubnetInfo.getId() + "!");
222 LOG.debug("Configured proxy arp for range {} to {} on node : {}!", startAndEndAddress.getLeft(),
223 startAndEndAddress.getRight(), hostName);
227 private void deleteProxyArpRange(String hostName,
229 GbpSubnet gbpSubnetInfo) throws LispConfigCommandFailedException {
230 Ipv4Prefix subnetPrefix = gbpSubnetInfo.getCidr().getIpv4Prefix();
232 Preconditions.checkNotNull(subnetPrefix, "Subnet CIDR found to be null for "
233 + "subnet uuid =" + gbpSubnetInfo.getId() + "!");
235 Pair<Ipv4Address, Ipv4Address> startAndEndAddress = IpAddressUtil.getStartAndEndIp(subnetPrefix);
237 if (!deleteArpRangesCommand(VppIidFactory.getNetconfNodeIid(new NodeId(hostName)),
239 startAndEndAddress.getLeft(),
240 startAndEndAddress.getRight())) {
241 throw new LispConfigCommandFailedException("Proxy arp configuration failed for subnet uuid: " +
242 gbpSubnetInfo.getId() + "!");
244 LOG.debug("Removed proxy arp for range {} to {} on node : {}!", startAndEndAddress.getLeft(),
245 startAndEndAddress.getRight(), hostName);
249 private boolean putArpRangesCommand(InstanceIdentifier<Node> iid, long vrf, Ipv4Address start, Ipv4Address end) {
250 ProxyRangeCommand.ProxyRangeCommandBuilder builder = new ProxyRangeCommand.ProxyRangeCommandBuilder();
251 builder.setOperation(General.Operations.PUT);
253 builder.setStartAddress(start);
254 builder.setEndAddress(end);
255 return GbpNetconfTransaction.netconfSyncedWrite(iid, builder.build(), GbpNetconfTransaction.RETRY_COUNT);
258 private boolean deleteArpRangesCommand(InstanceIdentifier<Node> iid,
262 ProxyRangeCommand.ProxyRangeCommandBuilder builder = new ProxyRangeCommand.ProxyRangeCommandBuilder();
263 builder.setOperation(General.Operations.DELETE);
265 builder.setStartAddress(start);
266 builder.setEndAddress(end);
267 return GbpNetconfTransaction.netconfSyncedDelete(iid, builder.build(), GbpNetconfTransaction.RETRY_COUNT);
270 private void addUnnumberedInterface(AddressEndpointWithLocation addressEp, String loopbackName) throws LispConfigCommandFailedException {
271 ExternalLocationCase loc = ConfigManagerHelper.resolveAndValidateLocation(addressEp);
272 InstanceIdentifier<Node> nodeIid = (InstanceIdentifier<Node>) loc.getExternalNodeMountPoint();
273 String neutronInterfaceName = loopbackManagerHelper.getInterfaceName(addressEp).get();
274 if (putUnnumberedInterface(nodeIid, neutronInterfaceName, loopbackName)) {
275 LOG.debug("Added Interface {} as unnumberd for {}", loopbackName, neutronInterfaceName);
277 throw new LispConfigCommandFailedException("Unnumbered configuration failed for " +
278 neutronInterfaceName + " - " + loopbackName);
282 private boolean putUnnumberedInterface(InstanceIdentifier<Node> iid, String interfaceFor, String interfaceWith) {
283 UnnumberedBuilder unnumberedBuilder = new UnnumberedBuilder();
284 unnumberedBuilder.setUse(interfaceWith);
285 InstanceIdentifier<Interface> interfaceIid = VppIidFactory.getInterfaceIID(new InterfaceKey(interfaceFor));
286 InterfaceUnnumberedAugmentationBuilder augBuilder = new InterfaceUnnumberedAugmentationBuilder();
287 augBuilder.setUnnumbered(unnumberedBuilder.build());
288 InterfaceBuilder interfaceBuilder = new InterfaceBuilder().setKey(new InterfaceKey(interfaceFor));
289 interfaceBuilder.addAugmentation(InterfaceUnnumberedAugmentation.class, augBuilder.build());
290 return GbpNetconfTransaction.netconfSyncedMerge(iid, interfaceIid, interfaceBuilder.build(),
291 GbpNetconfTransaction.RETRY_COUNT);
294 private void addGpeEntry(InstanceIdentifier<Node> iid, GbpSubnet gbpSubnetInfo, long vni) {
296 Pair<Ipv4Prefix, Ipv4Prefix> delegatingSubnets = IpAddressUtil
297 .getSmallerSubnet(gbpSubnetInfo.getCidr().getIpv4Prefix());
299 RemoteEid firstREid = LispUtil.toRemoteEid(LispUtil.toLispIpv4Prefix(delegatingSubnets.getLeft()),
301 Ipv4PrefixAfi.class);
302 putGpeEntry(iid, Constants.GPE_ENTRY_PREFIX + gbpSubnetInfo.getId() + "_1", firstREid, vni, vni);
304 if (delegatingSubnets.getLeft().equals(delegatingSubnets.getRight())) {
308 RemoteEid secondREid = LispUtil.toRemoteEid(LispUtil.toLispIpv4Prefix(delegatingSubnets.getRight()),
310 Ipv4PrefixAfi.class);
312 putGpeEntry(iid, Constants.GPE_ENTRY_PREFIX + gbpSubnetInfo.getId() + "_2", secondREid, vni, vni);
313 } catch (LispHelperArgumentException e) {
318 private boolean putGpeEntry(InstanceIdentifier<Node> iid, String id, RemoteEid rEid, long vni, long vrf) {
319 AbstractLispCommand<GpeEntry> gpeEntryCommand = LispCommandWrapper
320 .addGpeSendMapregisterAction(id, rEid, vni, vrf);
321 return LispStateCommandExecutor.executePutCommand(iid, gpeEntryCommand);
324 private boolean deleteGpeEntry(InstanceIdentifier<Node> iid, String id) {
325 AbstractLispCommand<GpeEntry> gpeEntryDeletionCommand = LispCommandWrapper
327 return LispStateCommandExecutor.executeDeleteCommand(iid, gpeEntryDeletionCommand);
330 private long getVni(String tenantUuid) {
331 return neutronTenantToVniMapper.getVni(tenantUuid);
334 private GbpSubnet getSubnetInfo(String subnetUuid) {
335 return subnetUuidToGbpSubnetMapper.getSubnetInfo(subnetUuid);