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.flat.overlay;
12 import com.google.common.base.Optional;
13 import com.google.common.base.Preconditions;
14 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
15 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
16 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.StaticArpCommand;
17 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.EndpointHost;
18 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.HostRelatedInfoContainer;
19 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.PhysicalInterfaces;
20 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.PortInterfaces;
21 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.PortRouteState;
22 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.SubnetState;
23 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.VrfHolder;
24 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.VrfState;
25 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.NeutronTenantToVniMapper;
26 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.util.ConfigManagerHelper;
27 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.util.Constants;
28 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.util.IpAddressUtil;
29 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.GbpNetconfTransaction;
30 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General;
31 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;
32 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
33 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.Config;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.TapCase;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpoint;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.Routing;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.RoutingBuilder;
45 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
49 import javax.annotation.Nonnull;
52 * Created by Shakib Ahmed on 5/2/17.
54 public class FlatOverlayManager {
55 private static final Logger LOG = LoggerFactory.getLogger(FlatOverlayManager.class);
57 private ConfigManagerHelper overlayHelper;
58 private DataBroker dataBroker;
60 private NeutronTenantToVniMapper neutronTenantToVniMapper = NeutronTenantToVniMapper.getInstance();
61 private HostRelatedInfoContainer hostRelatedInfoContainer = HostRelatedInfoContainer.getInstance();
63 private StaticRoutingHelper staticRoutingHelper;
65 public FlatOverlayManager(@Nonnull DataBroker dataBroker,
66 @Nonnull MountedDataBrokerProvider mountedDataBrokerProvider) {
67 this.overlayHelper = new ConfigManagerHelper(mountedDataBrokerProvider);
68 staticRoutingHelper = new StaticRoutingHelper();
69 this.dataBroker = dataBroker;
72 public void configureEndpointForFlatOverlay(AddressEndpointWithLocation addressEp) {
73 if (!overlayHelper.hasRelativeLocations(addressEp)) {
74 configureInterfaceForFlatOverlay(addressEp);
75 addStaticArp(addressEp);
76 addStaticRoute(addressEp);
78 Ipv4Address metadataIp = overlayHelper.getInterfaceIp(addressEp);
79 Ipv4Prefix metadataIpPrefix = overlayHelper.getInterfaceIpAsPrefix(addressEp);
80 addressEp.getRelativeLocations().getExternalLocation().forEach(externalLocation -> {
81 String hostName = overlayHelper.getHostName(externalLocation).get();
82 String metadataInterfaceName = overlayHelper.getInterfaceName(externalLocation).get();
84 long vrf = getVni(addressEp.getTenant().getValue());
86 String metadataSubnetUuid = Constants.METADATA_SUBNET_UUID;
88 PortInterfaces portInterfacesOfHost = hostRelatedInfoContainer.getPortInterfaceStateOfHost(hostName);
90 if (!portInterfacesOfHost.isInterfaceConfiguredForMetadata(metadataInterfaceName)) {
91 DataBroker vppDataBroker = overlayHelper.getPotentialExternalDataBroker(externalLocation).get();
92 addInterfaceInVrf(new EndpointHost(vppDataBroker, hostName), metadataInterfaceName, vrf);
93 String physicalAddress = resolvePhysicalAddress(hostName, metadataInterfaceName);
94 addStaticArp(vppDataBroker, hostName, metadataInterfaceName, physicalAddress, metadataIp);
95 addStaticRoute(vppDataBroker, hostName, vrf, metadataSubnetUuid, metadataIp,
96 metadataIpPrefix, metadataInterfaceName);
97 portInterfacesOfHost.addInterfaceInMetadataInterfaceSet(metadataInterfaceName);
103 private String resolvePhysicalAddress(String hostName, String metadataInterfaceName) {
104 String physAddress = null;
105 Optional<Config> configOptional =
106 DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, VppIidFactory.getVppRendererConfig(),
107 dataBroker.newReadOnlyTransaction());
108 if (configOptional.isPresent() && configOptional.get().getVppEndpoint() != null) {
109 java.util.Optional<VppEndpoint> vppEndpointOptional = configOptional.get().getVppEndpoint().stream()
110 .filter(vppEndpoint -> vppEndpoint.getVppNodeId().getValue().equals(hostName))
111 .filter(vppEndpoint -> vppEndpoint.getVppInterfaceName().equals(metadataInterfaceName))
113 if (vppEndpointOptional.isPresent() && vppEndpointOptional.get()
114 .getInterfaceTypeChoice() instanceof TapCase) {
115 TapCase tapCase = (TapCase) vppEndpointOptional.get().getInterfaceTypeChoice();
116 physAddress = tapCase.getPhysicalAddress().getValue();
117 LOG.trace("Resolved PhysicalAddress : {} for metadataInterfaceName: {}, on node: {}", physAddress
118 , metadataInterfaceName, hostName);
120 LOG.warn("PhysicalAddress was not resolved for metadataInterfaceName: {}, on node: {}",
121 metadataInterfaceName, hostName);
128 public void handleEndpointDeleteForFlatOverlay(AddressEndpointWithLocation addressEp) {
129 if (overlayHelper.hasRelativeLocations(addressEp)) {
131 // routes will be deleted on interface delete
134 deleteStaticRoute(addressEp);
137 public void handleInterfaceDeleteForFlatOverlay(DataBroker vppDataBroker, VppEndpoint vppEndpoint) {
138 String hostName = vppEndpoint.getVppNodeId().getValue();
139 String interfaceName = vppEndpoint.getVppInterfaceName();
141 staticRoutingHelper.deleteAllRoutesThroughInterface(vppDataBroker, hostName, interfaceName);
143 PortInterfaces portInterfaces = hostRelatedInfoContainer.getPortInterfaceStateOfHost(hostName);
144 portInterfaces.removePortInterface(interfaceName);
147 private void configureInterfaceForFlatOverlay(AddressEndpointWithLocation addressEp) {
148 addInterfaceInVrf(addressEp);
151 private void addInterfaceInVrf(AddressEndpointWithLocation addressEp) {
152 EndpointHost endpointHost = overlayHelper.getEndpointHostInformation(addressEp);
153 long vni = getVni(addressEp.getTenant().getValue());
155 Optional<String> interfaceNameOptional = overlayHelper.getInterfaceName(addressEp);
157 Preconditions.checkArgument(interfaceNameOptional.isPresent());
159 addInterfaceInVrf(endpointHost, interfaceNameOptional.get(), vrf);
162 private void addInterfaceInVrf(EndpointHost endpointHost, String interfaceName, long vrf) {
163 if (hostRelatedInfoContainer.getPortInterfaceStateOfHost(endpointHost.getHostName())
164 .isVrfConfiguredForInterface(interfaceName)) {
168 if (!putVrfInInterface(endpointHost.getHostDataBroker(), interfaceName, vrf)) {
169 LOG.warn("Failed to put interface {} to vrf {}", interfaceName, vrf);
171 hostRelatedInfoContainer
172 .getPortInterfaceStateOfHost(endpointHost.getHostName())
173 .initializeRoutingContextForInterface(interfaceName, vrf);
174 LOG.debug("Added interface {} to vrf {}", interfaceName, vrf);
178 private boolean putVrfInInterface(DataBroker vppDataBroker,
179 String interfaceName,
181 InstanceIdentifier<Routing> iid = VppIidFactory.getRoutingIid(new InterfaceKey(interfaceName));
182 RoutingBuilder builder = new RoutingBuilder();
183 builder.setIpv4VrfId(vrf);
184 return GbpNetconfTransaction.netconfSyncedWrite(vppDataBroker, iid, builder.build(), GbpNetconfTransaction.RETRY_COUNT);
187 private void addStaticArp(AddressEndpointWithLocation addressEp) {
188 DataBroker vppDataBroker = overlayHelper.getPotentialExternalDataBroker(addressEp).get();
189 String hostName = overlayHelper.getHostName(addressEp).get();
190 String physicalAddress = overlayHelper.getPhysicalAddress(addressEp);
191 Optional<String> interfaceNameOptional = overlayHelper.getInterfaceName(addressEp);
193 Preconditions.checkArgument(interfaceNameOptional.isPresent());
195 String interfaceName = interfaceNameOptional.get();
197 addStaticArp(vppDataBroker, hostName, interfaceName, physicalAddress, overlayHelper.getInterfaceIp(addressEp));
200 private void addStaticArp(DataBroker vppDataBroker,
202 String interfaceName,
203 String physicalAddress,
204 Ipv4Address ipv4Address) {
205 Ipv4AddressNoZone ip = new Ipv4AddressNoZone(ipv4Address);
206 InterfaceKey interfaceKey = new InterfaceKey(interfaceName);
207 if (!putStaticArp(vppDataBroker,
209 new PhysAddress(physicalAddress),
211 LOG.warn("Failed to put static arp with interface {} for ip={} and physical-address={}",
212 interfaceName, ip, physicalAddress);
214 LOG.debug("Added Static arp ({} {}) in host {} for interface {}", ip, physicalAddress, hostName,
219 private boolean putStaticArp(DataBroker vppDataBroker,
220 InterfaceKey interfaceKey,
221 PhysAddress physAddress,
222 Ipv4AddressNoZone ip) {
223 StaticArpCommand.StaticArpCommandBuilder staticArpCommandBuilder = new StaticArpCommand.StaticArpCommandBuilder();
225 staticArpCommandBuilder.setOperation(General.Operations.PUT);
226 staticArpCommandBuilder.setInterfaceKey(interfaceKey);
227 staticArpCommandBuilder.setIp(ip);
228 staticArpCommandBuilder.setLinkLayerAddress(physAddress);
230 return GbpNetconfTransaction.netconfSyncedWrite(vppDataBroker,
231 staticArpCommandBuilder.build(), GbpNetconfTransaction.RETRY_COUNT);
234 private void addStaticRoute(AddressEndpointWithLocation addressEp) {
235 DataBroker vppDataBroker = overlayHelper.getPotentialExternalDataBroker(addressEp).get();
236 String hostName = overlayHelper.getHostName(addressEp).get();
238 long vni = getVni(addressEp.getTenant().getValue());
241 String portSubnetUuid = overlayHelper.getSubnet(addressEp);
243 String outgoingInterfaceName = overlayHelper.getInterfaceName(addressEp).get();
244 Ipv4Address ipWithoutPrefix = overlayHelper.getInterfaceIp(addressEp);
246 if (overlayHelper.isMetadataPort(addressEp)) {
247 //override original port subnet to handle the Absolute location case of address endpoint
248 portSubnetUuid = Constants.METADATA_SUBNET_UUID;
251 Ipv4Prefix ipv4Prefix = overlayHelper.getInterfaceIpAsPrefix(addressEp);
253 addStaticRoute(vppDataBroker, hostName, vrf, portSubnetUuid, ipWithoutPrefix, ipv4Prefix, outgoingInterfaceName);
256 private void addStaticRoute(DataBroker vppDataBroker, String hostName, long vrfId, String hostIpSubnetUuid,
257 Ipv4Address ipWithoutPrefix, Ipv4Prefix ipv4Prefix, String outgoingInterfaceName) {
259 VrfHolder vrfHolderOfHost = hostRelatedInfoContainer.getVrfStateOfHost(hostName);
261 if (!vrfHolderOfHost.hasVrf(vrfId)) {
262 if (!staticRoutingHelper.addRoutingProtocolForVrf(vppDataBroker, vrfId, vrfHolderOfHost)) {
263 addStaticRouteToPublicInterface(vppDataBroker, hostName, vrfId);
264 LOG.warn("Failed to add Routing protocol for host {} and vrf {}!", hostName, vrfId);
268 VrfState vrfStateOfVrfId = vrfHolderOfHost.getVrfState(vrfId);
270 if (vrfStateOfVrfId.getSubnetHolder().getSubnetState(hostIpSubnetUuid).isIpPresent(ipWithoutPrefix)) {
271 LOG.info("Ip already exists in host {} vrf {} ip {}", hostName, vrfId, ipWithoutPrefix);
275 if (!staticRoutingHelper.addSingleStaticRouteInRoutingProtocol(vppDataBroker, hostName, vrfId, hostIpSubnetUuid,
276 ipWithoutPrefix, ipv4Prefix, outgoingInterfaceName)) {
277 LOG.warn("Failed to add routing ({} via {}) in vrf {} in compute host {}!",
278 ipv4Prefix, outgoingInterfaceName, vrfId, hostName);
280 LOG.debug("Added route ({} via {}) in vrf {} in compute host {}",
281 ipv4Prefix, outgoingInterfaceName, vrfId, hostName);
285 private void addStaticRouteToPublicInterface(DataBroker vppDataBroker, String hostName, long vrfId) {
286 Ipv4Address physicalInterfaceIp = hostRelatedInfoContainer
287 .getPhysicalInterfaceState(hostName)
288 .getIp(PhysicalInterfaces.PhysicalInterfaceType.PUBLIC).getIpv4Address();
289 String physicalInterfaceName = hostRelatedInfoContainer
290 .getPhysicalInterfaceState(hostName)
291 .getName(PhysicalInterfaces.PhysicalInterfaceType.PUBLIC);
292 if (physicalInterfaceName != null && !physicalInterfaceName.isEmpty()) {
293 if (!staticRoutingHelper.addSingleStaticRouteInRoutingProtocol(vppDataBroker,
294 hostName, vrfId, Constants.PUBLIC_SUBNET_UUID, physicalInterfaceIp,
295 IpAddressUtil.toIpV4Prefix(physicalInterfaceIp), physicalInterfaceName)) {
296 LOG.warn("Failed to add route for physical interface in vrf {} compute host {}", vrfId, hostName);
298 LOG.debug("Added route for physical interface {} in vrf {}", physicalInterfaceName, vrfId);
303 private void deleteStaticRoute(AddressEndpointWithLocation addressEp) {
304 DataBroker vppDataBroker = overlayHelper.getPotentialExternalDataBroker(addressEp).get();
305 String hostName = overlayHelper.getHostName(addressEp).get();
306 String interfaceName = overlayHelper.getInterfaceName(addressEp).get();
308 long vni = getVni(addressEp.getTenant().getValue());
311 String ipSubnetUuid = overlayHelper.getSubnet(addressEp);
313 if (overlayHelper.isMetadataPort(addressEp)) {
314 //override original port subnet to handle the Absolute location case of address endpoint
315 ipSubnetUuid = Constants.METADATA_SUBNET_UUID;
318 Ipv4Address ipWithoutPrefix = overlayHelper.getInterfaceIp(addressEp);
320 PortRouteState portRouteState = hostRelatedInfoContainer
321 .getPortInterfaceStateOfHost(hostName)
322 .getPortRouteState(interfaceName);
324 SubnetState subnetState = hostRelatedInfoContainer
325 .getVrfStateOfHost(hostName)
328 .getSubnetState(ipSubnetUuid);
330 if (!subnetState.isIpPresent(ipWithoutPrefix)) {
331 LOG.debug("Route {} already deleted from vrf {} of host {}", ipWithoutPrefix, vrfId, hostName);
335 long targetRouteId = portRouteState.getRouteIdOfIp(ipWithoutPrefix);
337 if (!staticRoutingHelper.deleteSingleStaticRouteFromRoutingProtocol(vppDataBroker,
342 LOG.warn("Failed to delete route ({} via {}) from vrf {} from host{}",
343 ipWithoutPrefix, interfaceName, vrfId, hostName);
346 portRouteState.removeIp(ipWithoutPrefix);
347 subnetState.removeIp(ipWithoutPrefix);
348 LOG.debug("Delete Static Route ({} via {}) from vrf {} from host {}",
349 ipWithoutPrefix, interfaceName, vrfId, hostName);
353 private long getVni(String tenantUuid) {
354 return neutronTenantToVniMapper.getVni(tenantUuid);