MRI version bumpup for Aluminium
[netvirt.git] / elanmanager / impl / src / test / java / org / opendaylight / netvirt / elanmanager / tests / Verifications.java
1 /*
2  * Copyright © 2017 Ericsson India Global Services Pvt Ltd. and others.  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 package org.opendaylight.netvirt.elanmanager.tests;
9
10 import static org.opendaylight.mdsal.common.api.LogicalDatastoreType.CONFIGURATION;
11
12 import com.google.common.collect.Sets;
13 import java.util.ArrayList;
14 import java.util.Collections;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Set;
18 import java.util.concurrent.ExecutionException;
19 import java.util.function.BiPredicate;
20 import java.util.function.Function;
21 import java.util.stream.Collectors;
22 import org.awaitility.core.ConditionFactory;
23 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
24 import org.opendaylight.genius.mdsalutil.MDSALUtil;
25 import org.opendaylight.genius.mdsalutil.NwConstants;
26 import org.opendaylight.genius.mdsalutil.actions.ActionGroup;
27 import org.opendaylight.genius.testutils.interfacemanager.TunnelInterfaceDetails;
28 import org.opendaylight.mdsal.binding.testutils.AssertDataObjects;
29 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
30 import org.opendaylight.mdsal.common.api.ReadFailedException;
31 import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
32 import org.opendaylight.netvirt.elan.utils.ElanConstants;
33 import org.opendaylight.netvirt.elan.utils.ElanUtils;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceInput;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceInputBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.BucketId;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.BucketBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.BucketKey;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacs;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.locator.set.attributes.LocatorSet;
61 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
62 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
63 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
64 import org.opendaylight.yangtools.yang.binding.DataObject;
65 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
66 import org.opendaylight.yangtools.yang.common.Uint32;
67 import org.opendaylight.yangtools.yang.common.Uint64;
68
69 public class Verifications {
70
71     private static final boolean CHECK_FOR_EXISTS = true;
72     private static final boolean CHECK_FOR_DELETED = false;
73     private static final Function<Uint64, NodeId> GET_OPENFLOW_NODE_ID = (dpnId) -> new NodeId("openflow:" + dpnId);
74     private static final InstanceIdentifier<ElanInstance> ELAN_IID = InstanceIdentifier
75             .builder(ElanInstances.class)
76             .child(ElanInstance.class, new ElanInstanceKey(ExpectedObjects.ELAN1))
77             .build();
78     private static final BiPredicate<Group, Group> BUCKETS_SIZE_MIS_MATCHED = (actual, expected) -> {
79         return !(actual.getBuckets().getBucket().size() == expected.getBuckets().getBucket().size());
80     };
81
82     private final SingleTransactionDataBroker singleTxdataBroker;
83     private final OdlInterfaceRpcService odlInterfaceRpcService;
84     private final Map<String, TunnelInterfaceDetails> extnIntfs;
85     private final ConditionFactory awaiter;
86
87     public Verifications(final SingleTransactionDataBroker singleTxdataBroker,
88                          final OdlInterfaceRpcService odlInterfaceRpcService,
89                          final Map<String, TunnelInterfaceDetails> extnIntfs,
90                          final ConditionFactory awaiter) {
91         this.singleTxdataBroker = singleTxdataBroker;
92         this.odlInterfaceRpcService = odlInterfaceRpcService;
93         this.extnIntfs = extnIntfs;
94         this.awaiter = awaiter;
95     }
96
97     private void awaitForData(LogicalDatastoreType dsType, InstanceIdentifier<? extends DataObject> iid) {
98         awaiter.until(() -> singleTxdataBroker.syncReadOptional(dsType, iid).isPresent());
99     }
100
101     private void awaitForDataDelete(LogicalDatastoreType dsType, InstanceIdentifier<? extends DataObject> iid) {
102         awaiter.until(() -> !singleTxdataBroker.syncReadOptional(dsType, iid).isPresent());
103     }
104
105     public void verifyThatMcastMacTepsCreated(InstanceIdentifier<Node> torNodeId, List<String> tepIps) {
106         for (String tepIp : tepIps) {
107             awaiter.until(() -> checkForRemoteMcastMac(torNodeId, tepIp, CHECK_FOR_EXISTS));
108         }
109     }
110
111     public void verifyThatMcastMacTepsDeleted(InstanceIdentifier<Node> torNodeId, List<String> tepIps) {
112         for (String tepIp : tepIps) {
113             awaiter.until(() -> checkForRemoteMcastMac(torNodeId, tepIp, CHECK_FOR_DELETED));
114         }
115     }
116
117     private boolean checkForRemoteMcastMac(InstanceIdentifier<Node> torNodeId, String tepIp, boolean checkForExists) {
118         try {
119             Node node = singleTxdataBroker.syncRead(LogicalDatastoreType.CONFIGURATION, torNodeId);
120             HwvtepGlobalAugmentation augmentation = node.augmentation(HwvtepGlobalAugmentation.class);
121             if (augmentation == null || augmentation.getRemoteMcastMacs() == null
122                     || augmentation.getRemoteMcastMacs().isEmpty()) {
123                 if (checkForExists) {
124                     return false;
125                 } else {
126                     return true;
127                 }
128             }
129             boolean remoteMcastFoundFlag = false;
130             for (RemoteMcastMacs remoteMcastMacs : augmentation.getRemoteMcastMacs().values()) {
131                 for (LocatorSet locatorSet : remoteMcastMacs.getLocatorSet()) {
132                     TpId tpId = locatorSet.getLocatorRef().getValue().firstKeyOf(TerminationPoint.class).getTpId();
133                     if (tpId.getValue().contains(tepIp)) {
134                         remoteMcastFoundFlag = true;
135                         break;
136                     }
137                 }
138             }
139             if (checkForExists) {
140                 return remoteMcastFoundFlag == true;
141             } else {
142                 return remoteMcastFoundFlag == false;
143             }
144         } catch (ReadFailedException e) {
145             return false;
146         }
147     }
148
149     public void verifyThatUcastCreated(InstanceIdentifier<Node> torNodeId, List<String> macs) {
150         for (String mac : macs) {
151             awaiter.until(() -> checkForRemoteUcastMac(torNodeId, mac, CHECK_FOR_EXISTS));
152         }
153     }
154
155     public void verifyThatUcastDeleted(InstanceIdentifier<Node> torNodeId, List<String> macs) {
156         for (String mac : macs) {
157             awaiter.until(() -> checkForRemoteUcastMac(torNodeId, mac, CHECK_FOR_DELETED));
158         }
159     }
160
161     public boolean checkForRemoteUcastMac(InstanceIdentifier<Node> torNodeId, String dpnMac, boolean checkForExists) {
162         try {
163             Node node = singleTxdataBroker.syncRead(LogicalDatastoreType.CONFIGURATION, torNodeId);
164             HwvtepGlobalAugmentation augmentation = node.augmentation(HwvtepGlobalAugmentation.class);
165             if (augmentation == null || augmentation.getRemoteUcastMacs() == null
166                     || augmentation.getRemoteUcastMacs().isEmpty()) {
167                 if (checkForExists) {
168                     return false;
169                 } else {
170                     return true;
171                 }
172             }
173             boolean remoteUcastFoundFlag = false;
174             for (RemoteUcastMacs remoteUcastMacs : augmentation.getRemoteUcastMacs().values()) {
175                 String mac = remoteUcastMacs.getMacEntryKey().getValue();
176                 if (mac.equals(dpnMac)) {
177                     remoteUcastFoundFlag = true;
178                     break;
179                 }
180             }
181             if (checkForExists) {
182                 return remoteUcastFoundFlag == true;
183             } else {
184                 return remoteUcastFoundFlag == false;
185             }
186         } catch (ReadFailedException e) {
187             return false;
188         }
189     }
190
191     private List<Bucket> buildRemoteBcGroupBuckets(ElanInstance elanInfo,
192                                                   List<Uint64> otherDpns,
193                                                   List<String> otherTors,
194                                                   Uint64 dpnId,
195                                                   int bucketId)
196             throws ExecutionException, InterruptedException {
197         List<Bucket> listBucketInfo = new ArrayList<>();
198         if (otherDpns != null) {
199             for (Uint64 otherDpn : otherDpns) {
200                 GetEgressActionsForInterfaceInput getEgressActInput = new GetEgressActionsForInterfaceInputBuilder()
201                         .setIntfName(extnIntfs.get(dpnId + ":" + otherDpn).getInterfaceInfo().getInterfaceName())
202                         .setTunnelKey(elanInfo.getElanTag().longValue() + ElanConstants.ELAN_TAG_ADDEND).build();
203                 List<Action> actionsList =
204                         new ArrayList<Action>(odlInterfaceRpcService.getEgressActionsForInterface(getEgressActInput)
205                                 .get().getResult().getAction().values());
206                 listBucketInfo.add(MDSALUtil.buildBucket(actionsList, MDSALUtil.GROUP_WEIGHT, bucketId,
207                         MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
208
209                 bucketId++;
210             }
211         }
212
213         if (otherTors != null) {
214             for (String otherTor : otherTors) {
215                 GetEgressActionsForInterfaceInput getEgressActInput = new GetEgressActionsForInterfaceInputBuilder()
216                         .setIntfName(extnIntfs.get(dpnId + ":" + otherTor).getInterfaceInfo().getInterfaceName())
217                         .setTunnelKey(elanInfo.getSegmentationId()).build();
218                 List<Action> actionsList =
219                         new ArrayList<Action>(odlInterfaceRpcService.getEgressActionsForInterface(getEgressActInput)
220                                 .get().getResult().getAction().values());
221                 listBucketInfo.add(MDSALUtil.buildBucket(actionsList, MDSALUtil.GROUP_WEIGHT, bucketId,
222                         MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
223
224                 bucketId++;
225             }
226         }
227         return listBucketInfo;
228     }
229
230     private Group buildStandardElanBroadcastGroups(ElanInstance elanInfo, Uint64 dpnId, List<Uint64> otherdpns,
231                                                   List<String> tepIps)
232             throws ExecutionException, InterruptedException {
233         List<Bucket> listBucket = new ArrayList<>();
234         int bucketId = 0;
235         int actionKey = 0;
236         Uint32 elanTag = elanInfo.getElanTag();
237         List<Action> listAction = new ArrayList<>();
238         listAction.add(new ActionGroup(ElanUtils.getElanLocalBCGId(elanTag.longValue())).buildAction(++actionKey));
239         listBucket.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT,
240                 MDSALUtil.WATCH_GROUP));
241         bucketId++;
242         listBucket.addAll(buildRemoteBcGroupBuckets(elanInfo, otherdpns, tepIps, dpnId, bucketId));
243         long groupId = ElanUtils.getElanRemoteBCGId(elanTag.longValue());
244         Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
245                 MDSALUtil.buildBucketLists(listBucket));
246         return group;
247     }
248
249     private boolean validateGroup(ElanInstance actualElanInstances,
250                                  Uint64 dpnId,
251                                  List<Uint64> otherdpns,
252                                  List<String> torips)
253             throws ExecutionException, InterruptedException, ReadFailedException, TransactionCommitFailedException {
254         Group expected = buildStandardElanBroadcastGroups(actualElanInstances, dpnId, otherdpns, torips);
255         InstanceIdentifier<Group> grpIid = DpnNodeBuilders.createGroupIid(expected, dpnId);
256         Group actual = singleTxdataBroker.syncRead(CONFIGURATION, grpIid);
257         singleTxdataBroker.syncWrite(CONFIGURATION, grpIid, expected);
258         expected = singleTxdataBroker.syncRead(CONFIGURATION, grpIid);
259
260         if (BUCKETS_SIZE_MIS_MATCHED.test(expected, actual)) {
261             AssertDataObjects.assertEqualBeans(expected, actual);
262         }
263
264         Set<Bucket> actualBuckets = modifyBucketId(new ArrayList<Bucket>(actual.getBuckets().getBucket().values()));
265         Set<Bucket> expectedBuckets = modifyBucketId(new ArrayList<Bucket>(expected.getBuckets().getBucket().values()));
266         Set<Bucket> diff = Sets.difference(actualBuckets, expectedBuckets);
267         if (diff != null && !diff.isEmpty()) {
268             AssertDataObjects.assertEqualBeans(expected, actual);
269         }
270         return true;
271     }
272
273     private static Set<Bucket> modifyBucketId(List<Bucket> input) {
274         return input.stream()
275                 .map(bucket -> new BucketBuilder(bucket).setBucketId(new BucketId(1L))
276                         .withKey(new BucketKey(new BucketId(1L))).build())
277                 .collect(Collectors.toSet());
278     }
279
280     public void verifyThatDpnGroupUpdated(Uint64 dpnId, List<Uint64> otherdpns, List<String> othertors)
281             throws ReadFailedException, TransactionCommitFailedException, ExecutionException, InterruptedException {
282         verifyDPNGroup(dpnId, otherdpns, othertors, CHECK_FOR_EXISTS);
283     }
284
285     public void verifyThatDpnGroupDeleted(Uint64 dpnId)
286             throws ReadFailedException, TransactionCommitFailedException, ExecutionException, InterruptedException {
287         verifyDPNGroup(dpnId, Collections.emptyList(), Collections.emptyList(), CHECK_FOR_DELETED);
288     }
289
290     public void verifyLocalBcGroup(Uint64 dpnId, int expectedNoBuckets)
291             throws ReadFailedException, TransactionCommitFailedException, ExecutionException, InterruptedException {
292         awaiter.until(() -> {
293             ElanInstance actualElanInstances = singleTxdataBroker.syncRead(CONFIGURATION, ELAN_IID);
294             InstanceIdentifier<Group> grpIid = buildLocalGroupIid(actualElanInstances, dpnId);
295             awaitForData(CONFIGURATION, grpIid);
296             Group localGroup = singleTxdataBroker.syncRead(CONFIGURATION, grpIid);
297             if (localGroup != null && localGroup.getBuckets() != null
298                     && localGroup.getBuckets().getBucket() != null) {
299                 return localGroup.getBuckets().getBucket().size() == expectedNoBuckets;
300             }
301             return false;
302         });
303     }
304
305     public void verifyThatLocalBcGroupDeleted(Uint64 dpnId)
306             throws ReadFailedException, TransactionCommitFailedException, ExecutionException, InterruptedException {
307         ElanInstance actualElanInstances = singleTxdataBroker.syncRead(CONFIGURATION, ELAN_IID);
308         InstanceIdentifier<Group> grpIid = buildLocalGroupIid(actualElanInstances, dpnId);
309         awaitForDataDelete(CONFIGURATION, grpIid);
310     }
311
312     public void verifyDPNGroup(Uint64 dpnId,
313                                List<Uint64> otherdpns,
314                                List<String> othertors,
315                                boolean checkForExists)
316             throws ReadFailedException, TransactionCommitFailedException, ExecutionException, InterruptedException {
317
318         ElanInstance actualElanInstances = singleTxdataBroker.syncRead(CONFIGURATION, ELAN_IID);
319         InstanceIdentifier<Group> grpIid = buildGroupIid(actualElanInstances, dpnId);
320
321         if (checkForExists) {
322             awaitForData(LogicalDatastoreType.CONFIGURATION, grpIid);
323             validateGroup(actualElanInstances, dpnId, otherdpns, othertors);
324         } else {
325             awaitForDataDelete(LogicalDatastoreType.CONFIGURATION, grpIid);
326         }
327     }
328
329     public void verifyThatDmacFlowOfTORCreated(List<Uint64> dpns,
330                                                InstanceIdentifier<Node> torNodeId,
331                                                List<String> macs) throws ReadFailedException {
332         for (String mac : macs) {
333             for (Uint64 srcDpnId : dpns) {
334                 verifyDmacFlowOfTOR(srcDpnId, torNodeId, mac, CHECK_FOR_EXISTS);
335             }
336         }
337     }
338
339     public void verifyThatDmacFlowOfTORDeleted(List<Uint64> dpns,
340                                                InstanceIdentifier<Node> torNodeId,
341                                                List<String> macs) throws ReadFailedException {
342         for (String mac : macs) {
343             for (Uint64 srcDpnId : dpns) {
344                 verifyDmacFlowOfTOR(srcDpnId, torNodeId, mac, CHECK_FOR_DELETED);
345             }
346         }
347     }
348
349     public void verifyDmacFlowOfTOR(Uint64 srcDpnId,
350                                     InstanceIdentifier<Node> torNodeIid,
351                                     String mac,
352                                     boolean checkForExists) throws ReadFailedException {
353
354         String torNodeId = torNodeIid.firstKeyOf(Node.class).getNodeId().getValue();
355         ElanInstance actualElanInstances = singleTxdataBroker.syncRead(CONFIGURATION, ELAN_IID);
356         FlowId flowId = new FlowId(
357                 ElanUtils.getKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE,
358                         srcDpnId,
359                         torNodeId,
360                         mac,
361                         actualElanInstances.getElanTag().toJava(),
362                         false));
363
364         InstanceIdentifier<Flow> flowIid = getFlowIid(NwConstants.ELAN_DMAC_TABLE, flowId, srcDpnId);
365
366         if (checkForExists) {
367             awaitForData(LogicalDatastoreType.CONFIGURATION, flowIid);
368         } else {
369             awaitForDataDelete(LogicalDatastoreType.CONFIGURATION, flowIid);
370         }
371     }
372
373     public void  verifyThatDmacOfOtherDpnCreated(Uint64 srcDpnId, Uint64 dpnId, List<String> dpnMacs)
374             throws ReadFailedException, InterruptedException {
375         for (String dpnMac : dpnMacs) {
376             verifyDmacFlowOfOtherDPN(srcDpnId, dpnId, dpnMac, CHECK_FOR_EXISTS);
377         }
378     }
379
380     public void  verifyThatDmacOfOtherDPNDeleted(Uint64 srcDpnId, Uint64 dpnId, List<String> dpnMacs)
381             throws ReadFailedException, InterruptedException {
382         for (String dpnMac : dpnMacs) {
383             verifyDmacFlowOfOtherDPN(srcDpnId, dpnId, dpnMac, CHECK_FOR_DELETED);
384         }
385     }
386
387     private void  verifyDmacFlowOfOtherDPN(Uint64 srcDpnId, Uint64 dpnId, String dpnMac, boolean createFlag)
388             throws ReadFailedException, InterruptedException {
389         InstanceIdentifier<ElanInstance> elanInstanceIid = InstanceIdentifier.builder(ElanInstances.class)
390                 .child(ElanInstance.class, new ElanInstanceKey(ExpectedObjects.ELAN1)).build();
391         ElanInstance actualElanInstances = singleTxdataBroker.syncRead(CONFIGURATION, elanInstanceIid);
392         FlowId flowId = new FlowId(
393                 ElanUtils.getKnownDynamicmacFlowRef(actualElanInstances.getElanTag(), dpnMac));
394         InstanceIdentifier<Flow> flowInstanceIidDst = getFlowIid(NwConstants.ELAN_DMAC_TABLE, flowId, srcDpnId);
395         if (createFlag) {
396             awaitForData(LogicalDatastoreType.CONFIGURATION, flowInstanceIidDst);
397         } else {
398             awaitForDataDelete(LogicalDatastoreType.CONFIGURATION, flowInstanceIidDst);
399         }
400     }
401
402     private static InstanceIdentifier<Flow> getFlowIid(short tableId, FlowId flowid, Uint64 dpnId) {
403
404         FlowKey flowKey = new FlowKey(new FlowId(flowid));
405         NodeId nodeId = GET_OPENFLOW_NODE_ID.apply(dpnId);
406         org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node nodeDpn =
407                 new NodeBuilder().setId(nodeId).withKey(new NodeKey(nodeId)).build();
408         return InstanceIdentifier.builder(Nodes.class)
409                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class,
410                         nodeDpn.key()).augmentation(FlowCapableNode.class)
411                 .child(Table.class, new TableKey(tableId)).child(Flow.class, flowKey).build();
412     }
413
414     private static InstanceIdentifier<Group> buildGroupIid(ElanInstance actualElanInstances, Uint64 dpnId) {
415         return DpnNodeBuilders.buildGroupInstanceIdentifier(
416                 ElanUtils.getElanRemoteBCGId(actualElanInstances.getElanTag().toJava()),
417                 DpnNodeBuilders.buildDpnNode(dpnId));
418     }
419
420     private static InstanceIdentifier<Group> buildLocalGroupIid(ElanInstance actualElanInstances, Uint64 dpnId) {
421         return DpnNodeBuilders.buildGroupInstanceIdentifier(
422                 ElanUtils.getElanLocalBCGId(actualElanInstances.getElanTag().toJava()),
423                 DpnNodeBuilders.buildDpnNode(dpnId));
424     }
425 }