2 * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. and others. 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
8 package org.opendaylight.vpnservice.fibmanager;
10 import com.google.common.base.Optional;
11 import com.google.common.util.concurrent.FutureCallback;
12 import com.google.common.util.concurrent.Futures;
14 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
15 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
16 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
17 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
18 import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
19 import org.opendaylight.vpnservice.mdsalutil.ActionType;
20 import org.opendaylight.vpnservice.mdsalutil.BucketInfo;
21 import org.opendaylight.vpnservice.mdsalutil.GroupEntity;
22 import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
23 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
24 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
25 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
26 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddressBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCase;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetFieldCase;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.AdjacencyKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetExternalTunnelInterfaceNameInputBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetExternalTunnelInterfaceNameOutput;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetTunnelInterfaceNameInputBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetTunnelInterfaceNameOutput;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInput;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInputBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutput;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.CreateIdPoolInput;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.CreateIdPoolInputBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInput;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInputBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetEgressActionsForInterfaceInputBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetEgressActionsForInterfaceOutput;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.L3nexthop;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.VpnNexthops;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.VpnNexthopsKey;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.vpnnexthops.VpnNexthop;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.vpnnexthops.VpnNexthopBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.vpnnexthops.VpnNexthopKey;
59 import org.opendaylight.yangtools.yang.binding.DataObject;
60 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
61 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
62 import org.opendaylight.yangtools.yang.common.RpcResult;
63 import org.slf4j.Logger;
64 import org.slf4j.LoggerFactory;
66 import java.math.BigInteger;
67 import java.util.ArrayList;
68 import java.util.List;
69 import java.util.concurrent.ExecutionException;
70 import java.util.concurrent.Future;
72 public class NexthopManager implements AutoCloseable {
73 private static final Logger LOG = LoggerFactory.getLogger(NexthopManager.class);
74 private final DataBroker broker;
75 private IMdsalApiManager mdsalManager;
76 private OdlInterfaceRpcService interfaceManager;
77 private ItmRpcService itmManager;
78 private IdManagerService idManager;
79 private static final short LPORT_INGRESS_TABLE = 0;
80 private static final short LFIB_TABLE = 20;
81 private static final short FIB_TABLE = 21;
82 private static final short DEFAULT_FLOW_PRIORITY = 10;
83 private static final String NEXTHOP_ID_POOL_NAME = "nextHopPointerPool";
85 private static final FutureCallback<Void> DEFAULT_CALLBACK =
86 new FutureCallback<Void>() {
87 public void onSuccess(Void result) {
88 LOG.debug("Success in Datastore write operation");
90 public void onFailure(Throwable error) {
91 LOG.error("Error in Datastore write operation", error);
96 * Provides nexthop functions
97 * Creates group ID pool
99 * @param db - dataBroker reference
101 public NexthopManager(final DataBroker db) {
106 public void close() throws Exception {
107 LOG.info("NextHop Manager Closed");
110 public void setInterfaceManager(OdlInterfaceRpcService ifManager) {
111 this.interfaceManager = ifManager;
114 public void setMdsalManager(IMdsalApiManager mdsalManager) {
115 this.mdsalManager = mdsalManager;
118 public void setIdManager(IdManagerService idManager) {
119 this.idManager = idManager;
120 createNexthopPointerPool();
123 public void setITMRpcService(ItmRpcService itmManager) {
124 this.itmManager = itmManager;
127 protected void createNexthopPointerPool() {
128 CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
129 .setPoolName(NEXTHOP_ID_POOL_NAME)
133 //TODO: Error handling
134 Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
135 LOG.trace("NextHopPointerPool result : {}", result);
138 private BigInteger getDpnId(String ofPortId) {
139 String[] fields = ofPortId.split(":");
140 BigInteger dpn = new BigInteger(fields[1]);
141 LOG.debug("DpnId: {}", dpn);
145 private String getNextHopKey(long vpnId, String ipAddress){
146 String nhKey = new String("nexthop." + vpnId + ipAddress);
150 private String getNextHopKey(String ifName, String ipAddress){
151 String nhKey = new String("nexthop." + ifName + ipAddress);
155 protected long createNextHopPointer(String nexthopKey) {
156 AllocateIdInput getIdInput = new AllocateIdInputBuilder()
157 .setPoolName(NEXTHOP_ID_POOL_NAME).setIdKey(nexthopKey)
159 //TODO: Proper error handling once IdManager code is complete
161 Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
162 RpcResult<AllocateIdOutput> rpcResult = result.get();
163 return rpcResult.getResult().getIdValue();
164 } catch (NullPointerException | InterruptedException | ExecutionException e) {
170 protected void removeNextHopPointer(String nexthopKey) {
171 ReleaseIdInput idInput = new ReleaseIdInputBuilder().
172 setPoolName(NEXTHOP_ID_POOL_NAME)
173 .setIdKey(nexthopKey).build();
175 Future<RpcResult<Void>> result = idManager.releaseId(idInput);
176 RpcResult<Void> rpcResult = result.get();
177 if(!rpcResult.isSuccessful()) {
178 LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
180 } catch (InterruptedException | ExecutionException e) {
181 LOG.warn("Exception when getting Unique Id for key {}", nexthopKey, e);
185 protected List<ActionInfo> getEgressActionsForInterface(String ifName) {
186 List<ActionInfo> listActionInfo = new ArrayList<ActionInfo>();
188 Future<RpcResult<GetEgressActionsForInterfaceOutput>> result =
189 interfaceManager.getEgressActionsForInterface(
190 new GetEgressActionsForInterfaceInputBuilder().setIntfName(ifName).build());
191 RpcResult<GetEgressActionsForInterfaceOutput> rpcResult = result.get();
192 if(!rpcResult.isSuccessful()) {
193 LOG.warn("RPC Call to Get egress actions for interface {} returned with Errors {}", ifName, rpcResult.getErrors());
195 List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> actions =
196 rpcResult.getResult().getAction();
197 for (Action action : actions) {
198 org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action actionClass = action.getAction();
199 if (actionClass instanceof OutputActionCase) {
200 listActionInfo.add(new ActionInfo(ActionType.output,
201 new String[] {((OutputActionCase)actionClass).getOutputAction()
202 .getOutputNodeConnector().getValue()}));
203 } else if (actionClass instanceof PushVlanActionCase) {
204 listActionInfo.add(new ActionInfo(ActionType.push_vlan, new String[] {}));
205 } else if (actionClass instanceof SetFieldCase) {
206 if (((SetFieldCase)actionClass).getSetField().getVlanMatch() != null) {
207 int vlanVid = ((SetFieldCase)actionClass).getSetField().getVlanMatch().getVlanId().getVlanId().getValue();
208 listActionInfo.add(new ActionInfo(ActionType.set_field_vlan_vid,
209 new String[] { Long.toString(vlanVid) }));
214 } catch (InterruptedException | ExecutionException e) {
215 LOG.warn("Exception when egress actions for interface {}", ifName, e);
217 return listActionInfo;
220 protected String getTunnelInterfaceName(BigInteger srcDpId, BigInteger dstDpId) {
221 // FIXME: Enable during itm integration
224 Future<RpcResult<GetTunnelInterfaceNameOutput>> result = itmManager.getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder()
225 .setSourceDpid(srcDpId)
226 .setDestinationDpid(dstDpId).build());
227 RpcResult<GetTunnelInterfaceNameOutput> rpcResult = result.get();
228 if(!rpcResult.isSuccessful()) {
229 LOG.warn("RPC Call to getTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
231 return rpcResult.getResult().getInterfaceName();
233 } catch (InterruptedException | ExecutionException e) {
234 LOG.warn("Exception when getting tunnel interface Id for tunnel between {} and {}", srcDpId, dstDpId, e);
240 protected String getExternalTunnelInterfaceName(BigInteger srcDpId, IpAddress dstIp) {
241 // FIXME: Enable during itm integration
244 Future<RpcResult<GetExternalTunnelInterfaceNameOutput>> result = itmManager.getExternalTunnelInterfaceName(new GetExternalTunnelInterfaceNameInputBuilder()
245 .setSourceDpid(srcDpId)
246 .setDestinationIp(dstIp).build());
247 RpcResult<GetExternalTunnelInterfaceNameOutput> rpcResult = result.get();
248 if(!rpcResult.isSuccessful()) {
249 LOG.warn("RPC Call to getExternalTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
251 return rpcResult.getResult().getInterfaceName();
253 } catch (InterruptedException | ExecutionException e) {
254 LOG.warn("Exception when getting external tunnel interface Id for tunnel between {} and {}", srcDpId, dstIp, e);
260 public long createLocalNextHop(long vpnId, BigInteger dpnId,
261 String ifName, String ipAddress) {
262 long groupId = createNextHopPointer(getNextHopKey(vpnId, ipAddress));
263 String nextHopLockStr = new String(vpnId + ipAddress);
264 synchronized (nextHopLockStr.intern()) {
265 VpnNexthop nexthop = getVpnNexthop(vpnId, ipAddress);
266 LOG.trace("nexthop: {}", nexthop);
267 if (nexthop == null) {
268 Optional<Adjacency> adjacencyData =
269 read(LogicalDatastoreType.OPERATIONAL, getAdjacencyIdentifier(ifName, ipAddress));
270 String macAddress = adjacencyData.isPresent() ? adjacencyData.get().getMacAddress() : null;
271 List<BucketInfo> listBucketInfo = new ArrayList<BucketInfo>();
272 List<ActionInfo> listActionInfo = getEgressActionsForInterface(ifName);
273 BucketInfo bucket = new BucketInfo(listActionInfo);
275 if (macAddress != null) {
276 listActionInfo.add(0, new ActionInfo(ActionType.set_field_eth_dest, new String[]{macAddress}));
277 //listActionInfo.add(0, new ActionInfo(ActionType.pop_mpls, new String[]{}));
279 //FIXME: Log message here.
280 LOG.debug("mac address for new local nexthop is null");
282 listBucketInfo.add(bucket);
283 GroupEntity groupEntity = MDSALUtil.buildGroupEntity(
284 dpnId, groupId, ipAddress, GroupTypes.GroupIndirect, listBucketInfo);
287 addVpnNexthopToDS(dpnId, vpnId, ipAddress, groupId);
290 // FIXME: mdsalManager.syncInstallGroup(groupEntity);
291 mdsalManager.installGroup(groupEntity);
294 //nexthop exists already; a new flow is going to point to it, increment the flowrefCount by 1
295 int flowrefCnt = nexthop.getFlowrefCount() + 1;
296 VpnNexthop nh = new VpnNexthopBuilder().setKey(new VpnNexthopKey(ipAddress)).setFlowrefCount(flowrefCnt).build();
297 LOG.trace("Updating vpnnextHop {} for refCount {} to Operational DS", nh, flowrefCnt);
298 syncWrite(LogicalDatastoreType.OPERATIONAL, getVpnNextHopIdentifier(vpnId, ipAddress), nh, DEFAULT_CALLBACK);
306 protected void addVpnNexthopToDS(BigInteger dpnId, long vpnId, String ipPrefix, long egressPointer) {
308 InstanceIdentifierBuilder<VpnNexthops> idBuilder = InstanceIdentifier.builder(
310 .child(VpnNexthops.class, new VpnNexthopsKey(vpnId));
312 // Add nexthop to vpn node
313 VpnNexthop nh = new VpnNexthopBuilder().
314 setKey(new VpnNexthopKey(ipPrefix)).
316 setIpAddress(ipPrefix).
318 setEgressPointer(egressPointer).build();
320 InstanceIdentifier<VpnNexthop> id1 = idBuilder
321 .child(VpnNexthop.class, new VpnNexthopKey(ipPrefix)).build();
322 LOG.trace("Adding vpnnextHop {} to Operational DS", nh);
323 syncWrite(LogicalDatastoreType.OPERATIONAL, id1, nh, DEFAULT_CALLBACK);
329 protected InstanceIdentifier<VpnNexthop> getVpnNextHopIdentifier(long vpnId, String ipAddress) {
330 InstanceIdentifier<VpnNexthop> id = InstanceIdentifier.builder(
332 .child(VpnNexthops.class, new VpnNexthopsKey(vpnId)).child(VpnNexthop.class, new VpnNexthopKey(ipAddress)).build();
336 protected VpnNexthop getVpnNexthop(long vpnId, String ipAddress) {
338 // check if vpn node is there
339 InstanceIdentifierBuilder<VpnNexthops> idBuilder =
340 InstanceIdentifier.builder(L3nexthop.class).child(VpnNexthops.class,
341 new VpnNexthopsKey(vpnId));
342 InstanceIdentifier<VpnNexthops> id = idBuilder.build();
343 Optional<VpnNexthops> vpnNexthops = read(LogicalDatastoreType.OPERATIONAL, id);
344 if (vpnNexthops.isPresent()) {
345 // get nexthops list for vpn
346 List<VpnNexthop> nexthops = vpnNexthops.get().getVpnNexthop();
347 for (VpnNexthop nexthop : nexthops) {
348 if (nexthop.getIpAddress().equals(ipAddress)) {
350 LOG.trace("VpnNextHop : {}", nexthop);
354 // return null if not found
360 public String getRemoteNextHopPointer(BigInteger localDpnId, BigInteger remoteDpnId,
361 long vpnId, String prefixIp, String nextHopIp) {
362 String tunnelIfName = null;
363 LOG.trace("getRemoteNextHopPointer: input [localDpnId {} remoteDpnId {}, vpnId {}, prefixIp {}, nextHopIp {} ]",
364 localDpnId, remoteDpnId, vpnId, prefixIp, nextHopIp);
366 // check if the incoming VM is within the same DC. If so, retrieve the local tunnel group pointer.
367 // Else retrieve the tunnel to DC gateway group pointer.
369 if (localDpnId == null || BigInteger.ZERO.equals(localDpnId)) {
370 VpnNexthop vpnNexthop = getVpnNexthop(vpnId, prefixIp);
371 //If the vrf entry is a static/extra route, the nexthop of the entry would be a adjacency in the vpn
372 if(vpnNexthop == null) {
373 vpnNexthop = getVpnNexthop(vpnId, nextHopIp + "/32");
375 localDpnId = (vpnNexthop == null) ? null : vpnNexthop.getDpnId();
377 LOG.trace("getRemoteNextHopPointer: Calling ITM with localDpnId {} ", localDpnId);
379 // here use the config for tunnel type param
380 if(localDpnId != null){
382 tunnelIfName = getTunnelInterfaceName(remoteDpnId, localDpnId);
385 tunnelIfName = getExternalTunnelInterfaceName(remoteDpnId,
386 IpAddressBuilder.getDefaultInstance(nextHopIp));
388 }catch(Exception ex){
389 LOG.error("Error while retrieving nexthop pointer for DC Gateway : ", ex.getMessage());
394 public BigInteger getDpnForPrefix(long vpnId, String prefixIp) {
395 VpnNexthop vpnNexthop = getVpnNexthop(vpnId, prefixIp);
396 BigInteger localDpnId = (vpnNexthop == null) ? null : vpnNexthop.getDpnId();
401 private void removeVpnNexthopFromDS(long vpnId, String ipPrefix) {
403 InstanceIdentifierBuilder<VpnNexthop> idBuilder = InstanceIdentifier.builder(L3nexthop.class)
404 .child(VpnNexthops.class, new VpnNexthopsKey(vpnId))
405 .child(VpnNexthop.class, new VpnNexthopKey(ipPrefix));
406 InstanceIdentifier<VpnNexthop> id = idBuilder.build();
408 LOG.trace("Removing vpn next hop from datastore : {}", id);
409 delete(LogicalDatastoreType.OPERATIONAL, id);
413 public void removeLocalNextHop(BigInteger dpnId, Long vpnId, String ipAddress) {
415 String nextHopLockStr = new String(vpnId + ipAddress);
416 synchronized (nextHopLockStr.intern()) {
417 VpnNexthop nh = getVpnNexthop(vpnId, ipAddress);
419 int newFlowrefCnt = nh.getFlowrefCount() - 1;
420 if (newFlowrefCnt == 0) { //remove the group only if there are no more flows using this group
421 GroupEntity groupEntity = MDSALUtil.buildGroupEntity(
422 dpnId, nh.getEgressPointer(), ipAddress, GroupTypes.GroupIndirect, null);
424 // FIXME: mdsalManager.syncRemoveGroup(groupEntity);
425 mdsalManager.removeGroup(groupEntity);
427 removeVpnNexthopFromDS(vpnId, ipAddress);
429 removeNextHopPointer(getNextHopKey(vpnId, ipAddress));
430 LOG.debug("Local Next hop for {} on dpn {} successfully deleted", ipAddress, dpnId);
432 //just update the flowrefCount of the vpnNexthop
433 VpnNexthop currNh = new VpnNexthopBuilder().setKey(new VpnNexthopKey(ipAddress)).setFlowrefCount(newFlowrefCnt).build();
434 LOG.trace("Updating vpnnextHop {} for refCount {} to Operational DS", currNh, newFlowrefCnt);
435 syncWrite(LogicalDatastoreType.OPERATIONAL, getVpnNextHopIdentifier(vpnId, ipAddress), currNh, DEFAULT_CALLBACK);
439 LOG.error("Local Next hop for {} on dpn {} not deleted", ipAddress, dpnId);
446 private <T extends DataObject> Optional<T> read(LogicalDatastoreType datastoreType,
447 InstanceIdentifier<T> path) {
449 ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
451 Optional<T> result = Optional.absent();
453 result = tx.read(datastoreType, path).get();
454 } catch (Exception e) {
455 throw new RuntimeException(e);
461 private <T extends DataObject> void asyncWrite(LogicalDatastoreType datastoreType,
462 InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
463 WriteTransaction tx = broker.newWriteOnlyTransaction();
464 tx.merge(datastoreType, path, data, true);
465 Futures.addCallback(tx.submit(), callback);
468 private <T extends DataObject> void syncWrite(LogicalDatastoreType datastoreType,
469 InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
470 WriteTransaction tx = broker.newWriteOnlyTransaction();
471 tx.merge(datastoreType, path, data, true);
475 private <T extends DataObject> void delete(LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
476 WriteTransaction tx = broker.newWriteOnlyTransaction();
477 tx.delete(datastoreType, path);
478 Futures.addCallback(tx.submit(), DEFAULT_CALLBACK);
481 private InstanceIdentifier<Adjacency> getAdjacencyIdentifier(String vpnInterfaceName, String ipAddress) {
482 return InstanceIdentifier.builder(VpnInterfaces.class)
483 .child(VpnInterface.class, new VpnInterfaceKey(vpnInterfaceName)).augmentation(
484 Adjacencies.class).child(Adjacency.class, new AdjacencyKey(ipAddress)).build();