Policy exclusions & parallel netconf transactions
[groupbasedpolicy.git] / renderers / vpp / src / main / java / org / opendaylight / groupbasedpolicy / renderer / vpp / lisp / util / ConfigManagerHelper.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.util;
10
11 import java.util.List;
12 import java.util.Map;
13 import java.util.Set;
14
15 import javax.annotation.Nonnull;
16
17 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
19 import org.opendaylight.groupbasedpolicy.renderer.vpp.config.ConfigUtil;
20 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.VppPathMapper;
21 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.LispStateManager;
22 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.exception.LispNotFoundException;
23 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.EndpointHost;
24 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.HostRelatedInfoContainer;
25 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.LispState;
26 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.PhysicalInterfaces;
27 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.GbpNetconfTransaction;
28 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.InterfaceUtil;
29 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.LispUtil;
30 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;
31 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.EthernetCsmacd;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface1;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface2;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.Ipv4;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.ipv4.Address;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.ipv4.address.subnet.PrefixLength;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.Ipv4Afi;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.Containment;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.containment.NetworkDomainContainment;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.LocationType;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCase;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.child.endpoints.ChildEndpoint;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.relative.location.relative.locations.ExternalLocation;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.ParentEndpointChoice;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.ParentEndpointCase;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpoint;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.IpPrefixType;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.L3Context;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.MacAddressType;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpoint;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.HmacKeyType;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.dp.subtable.grouping.local.mappings.local.mapping.Eid;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.hmac.key.grouping.HmacKey;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.Routing;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.RoutingBuilder;
64 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
65 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
66 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
67 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
68 import org.slf4j.Logger;
69 import org.slf4j.LoggerFactory;
70
71 import com.google.common.base.Optional;
72 import com.google.common.base.Preconditions;
73 import com.google.common.util.concurrent.Futures;
74 import com.google.common.util.concurrent.ListenableFuture;
75
76
77 /**
78  * Created by Shakib Ahmed on 3/31/17.
79  */
80 public class ConfigManagerHelper {
81     private static final Logger LOG = LoggerFactory.getLogger(ConfigManagerHelper.class);
82
83     private MountedDataBrokerProvider mountedDataBrokerProvider;
84
85     public ConfigManagerHelper(MountedDataBrokerProvider mountedDataBrokerProvider) {
86         this.mountedDataBrokerProvider = mountedDataBrokerProvider;
87     }
88
89     public EndpointHost getEndpointHostInformation(AddressEndpointWithLocation addressEpWithLoc) {
90         DataBroker endpointHostDataBroker = getPotentialExternalDataBroker(addressEpWithLoc).get();
91         String hostName = getHostName(addressEpWithLoc).get();
92         return new EndpointHost(endpointHostDataBroker, hostName);
93     }
94
95     public Optional<DataBroker> getPotentialExternalDataBroker(AddressEndpointWithLocation addressEpWithLoc) {
96         ExternalLocationCase externalLocationCase = resolveAndValidateLocation(addressEpWithLoc);
97         InstanceIdentifier<Node> vppNodeIid =
98                 (InstanceIdentifier<Node>) externalLocationCase.getExternalNodeMountPoint();
99         String interfacePath = externalLocationCase.getExternalNodeConnector();
100
101         Optional<DataBroker>
102                 potentialVppDataProvider = mountedDataBrokerProvider.resolveDataBrokerForMountPoint(vppNodeIid);
103
104         Preconditions.checkArgument(potentialVppDataProvider.isPresent(),
105                 "Cannot resolve data broker for interface path: {}", interfacePath);
106
107         return potentialVppDataProvider;
108     }
109
110     public Optional<DataBroker> getPotentialExternalDataBroker(ExternalLocation externalLocation) {
111         InstanceIdentifier<Node> vppNodeIid = (InstanceIdentifier<Node>) externalLocation.getExternalNodeMountPoint();
112
113         Optional<DataBroker> potentialVppDataProvider;
114         potentialVppDataProvider = mountedDataBrokerProvider.resolveDataBrokerForMountPoint(vppNodeIid);
115
116         Preconditions.checkState(potentialVppDataProvider.isPresent(), "Data Broker missing");
117
118         return potentialVppDataProvider;
119     }
120
121     public Optional<DataBroker> getPotentialExternalDataBroker(VppEndpoint vppEp) {
122         InstanceIdentifier<Node> vppNodeIid = VppIidFactory.getNetconfNodeIid(vppEp.getVppNodeId());
123         Optional<DataBroker> potentialVppDataProvider =
124                 mountedDataBrokerProvider.resolveDataBrokerForMountPoint(vppNodeIid);
125
126         Preconditions.checkArgument(potentialVppDataProvider.isPresent(),
127                 "Cannot resolve data broker for Vpp Endpoint: {}", vppEp);
128         return potentialVppDataProvider;
129     }
130
131     public Optional<DataBroker> getPotentialExternalDataBroker(String hostId) {
132         InstanceIdentifier<Node> nodeIid = VppIidFactory.getNetconfNodeIid(new NodeId(hostId));
133         Optional<DataBroker> potentialVppDataProvider =
134                 mountedDataBrokerProvider.resolveDataBrokerForMountPoint(nodeIid);
135         Preconditions.checkArgument(potentialVppDataProvider.isPresent(),
136                 "Data Broker not found for {}", hostId);
137         return potentialVppDataProvider;
138     }
139
140     public Optional<String> getHostName(AddressEndpointWithLocation addrEp) {
141         ExternalLocationCase locationCase = resolveAndValidateLocation(addrEp);
142         NodeKey nodeKey = locationCase.getExternalNodeMountPoint().firstKeyOf(Node.class);
143         String hostId = Preconditions.checkNotNull(nodeKey.getNodeId().getValue(),
144                 "Host Id extraction failed from address endpoint: {}", addrEp);
145         return Optional.fromNullable(hostId);
146     }
147
148     public Optional<String> getHostName(ExternalLocation externalLocation) {
149         NodeKey nodeKey = externalLocation.getExternalNodeMountPoint().firstKeyOf(Node.class);
150         String hostId = Preconditions.checkNotNull(nodeKey.getNodeId().getValue(),
151                 "Host Id extraction failed from address endpoint: {}", externalLocation);
152
153         return Optional.fromNullable(hostId);
154     }
155
156     public static ExternalLocationCase resolveAndValidateLocation(AddressEndpointWithLocation addrEpWithLoc) {
157         Preconditions.checkNotNull(addrEpWithLoc.getAbsoluteLocation(), "Absolute location for " +
158                 "AddressEndpointWithLocation missing: " + addrEpWithLoc.toString() );
159         LocationType locationType = addrEpWithLoc.getAbsoluteLocation().getLocationType();
160         if (!(locationType instanceof ExternalLocationCase)) {
161             throw new IllegalArgumentException("Endpoint does not have external location " + addrEpWithLoc);
162         }
163         ExternalLocationCase result = (ExternalLocationCase) locationType;
164         if (result.getExternalNodeMountPoint() == null || result.getExternalNodeConnector() == null) {
165             throw new IllegalArgumentException(
166                     "Endpoint does not have external-node-mount-point or external-node-connector " + addrEpWithLoc);
167         }
168         return result;
169     }
170
171     //This is almost identical to VBD's equivalent method
172     public ListenableFuture<String> getLispDataRlocInterfaceName(@Nonnull String hostName) {
173         Preconditions.checkNotNull(hostName, "Hostname is null!");
174
175         PhysicalInterfaces physicalInterfaces = HostRelatedInfoContainer.getInstance()
176                 .getPhysicalInterfaceState(hostName);
177
178         String publicInterfaceName = physicalInterfaces == null ? "" : physicalInterfaces
179                 .getName(PhysicalInterfaces.PhysicalInterfaceType.PUBLIC);
180
181         final Optional<InterfacesState> opInterfaceState =
182                 GbpNetconfTransaction.read(LispUtil.HOSTNAME_TO_IID.apply(hostName), LogicalDatastoreType.OPERATIONAL,
183                         InstanceIdentifier.create(InterfacesState.class), GbpNetconfTransaction.RETRY_COUNT);
184
185         if (!opInterfaceState.isPresent()) {
186             LOG.debug("There appear to be no interfaces on node {}.", hostName);
187             return Futures.immediateFailedFuture(new LispNotFoundException("No interfaces found"));
188         }
189
190         String interfaceName = null;
191         for(Interface intf: opInterfaceState.get().getInterface()) {
192             if(!ipAddressPresent(intf)) {
193                 continue;
194             }
195             interfaceName = intf.getName();
196         }
197
198         final Optional<Interfaces> opInterfaces =
199                 GbpNetconfTransaction.read(LispUtil.HOSTNAME_TO_IID.apply(hostName), LogicalDatastoreType.CONFIGURATION,
200                         InstanceIdentifier.create(Interfaces.class), GbpNetconfTransaction.RETRY_COUNT);
201
202
203         if (opInterfaces.isPresent()) {
204
205             List<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.
206                     interfaces.Interface> hostInterfaceFromOpDS = opInterfaces.get().getInterface();
207
208             for (org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.
209                     interfaces.Interface intf : hostInterfaceFromOpDS) {
210                 if (Constants.TENANT_INTERFACE.equals(intf.getDescription())
211                         && ipAddressPresent(intf)
212                         && intf.getType().equals(EthernetCsmacd.class)) {
213                     return Futures.immediateFuture(intf.getName());
214                 }
215             }
216
217             for (org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.
218                     interfaces.Interface intf : hostInterfaceFromOpDS) {
219                 if (ipAddressPresent(intf)
220                         && intf.getType().equals(EthernetCsmacd.class)
221                         && !intf.getName().equalsIgnoreCase(publicInterfaceName)) {
222                     return Futures.immediateFuture(intf.getName());
223                 }
224             }
225         }
226
227         if (interfaceName == null) {
228             LOG.warn("No interface with IP found for host {}", hostName);
229             return Futures.immediateFailedFuture(new LispNotFoundException("No interface with Ip address found!"));
230         }
231         return Futures.immediateFuture(interfaceName);
232     }
233
234     private boolean ipAddressPresent(Interface intf) {
235         Interface2 augIntf = intf.getAugmentation(Interface2.class);
236
237         if (augIntf == null) {
238             return false;
239         }
240
241         Ipv4 ipv4 = augIntf.getIpv4();
242
243         if (ipv4 == null) {
244             return false;
245         }
246
247         final List<Address> addresses = ipv4.getAddress();
248
249         if (addresses == null || addresses.isEmpty()) {
250             return false;
251         }
252
253         final Ipv4AddressNoZone ip = addresses.iterator().next().getIp();
254         return ip != null;
255     }
256
257     private String ipCidr(Interface intf) {
258         Interface2 augIntf = intf.getAugmentation(Interface2.class);
259
260         if (augIntf == null) {
261             return null;
262         }
263
264         Ipv4 ipv4 = augIntf.getIpv4();
265
266         if (ipv4 == null) {
267             return null;
268         }
269
270         final List<Address> addresses = ipv4.getAddress();
271
272         if (addresses == null || addresses.isEmpty()) {
273             return null;
274         }
275
276         Address firstAddress = addresses.get(0);
277         String ipString = firstAddress.getIp().getValue();
278         String length = "";
279         if (firstAddress.getSubnet().getImplementedInterface().equals(PrefixLength.class)) {
280             length = "" + ((PrefixLength)firstAddress.getSubnet()).getPrefixLength();
281         }
282
283         if (length.isEmpty()) {
284             return null;
285         }
286
287         return ipString + "/" + length;
288     }
289
290     private boolean ipAddressPresent(final org.opendaylight.yang.gen.v1.urn.ietf.
291             params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface intf) {
292         final Interface1 augIntf = intf.getAugmentation(Interface1.class);
293
294         if (augIntf == null) {
295             LOG.debug("Cannot get Interface1 augmentation for intf {}", intf);
296             return false;
297         }
298
299         final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv4 ipv4 =
300                 augIntf.getIpv4();
301         if (ipv4 == null) {
302             return false;
303         }
304
305         final List<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.Address> addresses =
306                 ipv4.getAddress();
307         if (addresses == null || addresses.isEmpty()) {
308             return false;
309         }
310
311         final Ipv4AddressNoZone ip = addresses.iterator().next().getIp();
312         return ip != null;
313     }
314
315     public String getLispCpRlocInterfaceName(@Nonnull EndpointHost endpointHost) {
316         List<Interface> operationalInterfaceList =
317                 InterfaceUtil.getOperationalInterfaces(LispUtil.HOSTNAME_TO_IID.apply(endpointHost.getHostName()));
318
319         if (operationalInterfaceList == null) {
320             return null;
321         } else {
322             int maxLen = -1;
323             String outgoingInterface = "";
324
325             for (Interface intf : operationalInterfaceList) {
326                 String ipCidr = ipCidr(intf);
327
328                 if (ipCidr == null) {
329                     continue;
330                 }
331
332                 if (IpAddressUtil.ipInRange(ConfigUtil.getInstance().getOdlIp().getIpv4Address(),
333                         IpAddressUtil.startIpOfSubnet(ipCidr), IpAddressUtil.endIpOfSubnet(ipCidr))) {
334                     int tmpLen = IpAddressUtil.maskLen(ipCidr);
335                     if (tmpLen > maxLen) {
336                         maxLen = tmpLen;
337                         outgoingInterface = intf.getName();
338                     }
339                 }
340             }
341             return outgoingInterface;
342         }
343     }
344
345     public String constructLocatorSetName(int locatorSetCount) {
346         return LispStateManager.DEFAULT_LOCATOR_SET_NAME_PREFIX + (locatorSetCount + 1);
347     }
348
349     public String constructLocatorSetNameForItrRloc() {
350         return LispStateManager.DEFAULT_LOCATOR_SET_NAME_PREFIX + "_itr_rloc";
351     }
352
353     public String constructEidMappingName(AddressEndpointWithLocation addressEp) {
354         String interfaceName = getInterfaceName(addressEp).get();
355         String ipAddress = getInterfaceIp(addressEp).getValue();
356         return LispStateManager.DEFAULT_MAPPINGRECORD_NAME_PREFIX + interfaceName + "_" + ipAddress;
357     }
358
359     public String getSubnet(AddressEndpointWithLocation addressEp) {
360         String subnetUuid = null;
361         Containment containment = addressEp.getNetworkContainment().getContainment();
362         if (containment instanceof NetworkDomainContainment) {
363             NetworkDomainContainment networkDomainContainment = (NetworkDomainContainment) containment;
364             subnetUuid = networkDomainContainment.getNetworkDomainId().getValue();
365         }
366         return subnetUuid;
367     }
368
369     public Eid getEid(AddressEndpointWithLocation addressEp, long vni) {
370         String ipPrefix = getIpWithPrefixOfEndpoint(addressEp);
371         return LispUtil.toEid(LispUtil.toIpv4(ipPrefix), vni, Ipv4Afi.class);
372     }
373
374     public String getIpWithPrefixOfEndpoint(AddressEndpointWithLocation addressEp) {
375         String ipPrefix = null;
376         if (addressEp.getAddressType().equals(IpPrefixType.class)) {
377             ipPrefix = addressEp.getAddress();
378         } else if (addressEp.getAddressType().equals(MacAddressType.class)) {
379             ParentEndpointChoice parentEndpointChoice = addressEp.getParentEndpointChoice();
380             if (parentEndpointChoice instanceof ParentEndpointCase) {
381                 java.util.Optional<ParentEndpoint> endpointOptional =
382                     ((ParentEndpointCase) parentEndpointChoice).getParentEndpoint().stream()
383                         .filter(choice -> choice.getAddressType().equals(IpPrefixType.class))
384                         .filter(choice -> choice.getContextType().equals(L3Context.class)).findFirst();
385                 if (endpointOptional.isPresent()) {
386                     ipPrefix = endpointOptional.get().getAddress();
387                 }
388             }
389         }
390         return Preconditions.checkNotNull(ipPrefix, "No IP address found for Address Endpoint: {}", addressEp);
391     }
392
393     public Ipv4Address getInterfaceIp(AddressEndpointWithLocation addressEp) {
394         String ipPrefix = getIpWithPrefixOfEndpoint(addressEp);
395         return LispUtil.toIpv4(ipPrefix).getIpv4();
396     }
397
398     public Ipv4Prefix getInterfaceIpAsPrefix(AddressEndpointWithLocation addressEp) {
399         if (getInterfaceIp(addressEp).getValue().contains("/")) {
400             return new Ipv4Prefix(getInterfaceIp(addressEp).getValue());
401         }
402         else {
403             return new Ipv4Prefix(getInterfaceIp(addressEp).getValue() + "/32");
404         }
405     }
406
407     public String getFirstLocatorSetName(LispState lispState) {
408         Set<Map.Entry<String, String >> locatorSet = lispState.getLocatorSetEntry();
409         Preconditions.checkNotNull(locatorSet, "No locator set found!");
410         if (!locatorSet.iterator().hasNext()) {
411             return null;
412         }
413
414         return locatorSet.iterator().next().getValue();
415     }
416
417     public Optional<String> getInterfaceName(AddressEndpointWithLocation addedEp) {
418         ExternalLocationCase epLoc = resolveAndValidateLocation(addedEp);
419         String interfacePath = epLoc.getExternalNodeConnector();
420
421         return VppPathMapper.interfacePathToInterfaceName(interfacePath);
422     }
423
424     public Optional<String> getInterfaceName(ExternalLocation externalLocation) {
425         String interfacePath = externalLocation.getExternalNodeConnector();
426         return VppPathMapper.interfacePathToInterfaceName(interfacePath);
427     }
428
429     public HmacKey getDefaultHmacKey() {
430         return LispUtil.toHmacKey(HmacKeyType.Sha196Key, LispStateManager.DEFAULT_XTR_KEY);
431     }
432
433     public String getPhysicalAddress(AddressEndpointWithLocation addressEp) {
434         String physicalAddress = null;
435
436         if (addressEp.getAddressType().equals(MacAddressType.class)) {
437             physicalAddress = addressEp.getAddress();
438         } else {
439             List<ChildEndpoint> childEndpoints = addressEp.getChildEndpoint();
440             for (ChildEndpoint childEndpoint : childEndpoints) {
441                 if (childEndpoint.getAddressType().equals(MacAddressType.class)) {
442                     physicalAddress = childEndpoint.getAddress();
443                     break;
444                 }
445             }
446         }
447         return Preconditions.checkNotNull(physicalAddress, "Physical address not found " +
448                 "in address endpoint: " + addressEp);
449     }
450
451     public boolean hasRelativeLocations(AddressEndpointWithLocation addedEp) {
452         return addedEp.getRelativeLocations() != null && addedEp.getRelativeLocations().getExternalLocation() != null;
453     }
454
455     public boolean isMetadataPort(AddressEndpointWithLocation addressEp) {
456         return hasRelativeLocations(addressEp) || IpAddressUtil.isMetadataIp(getInterfaceIp(addressEp));
457     }
458
459     public String getGatewayInterfaceName(String gwNamePrefix, String subnetUuid) {
460         return gwNamePrefix + subnetUuid;
461     }
462
463     public Routing getRouting(long vrf) {
464         return new RoutingBuilder().setIpv4VrfId(vrf).build();
465     }
466 }