- /**
- * Builds a Flow to be programmed in a DPN's DMAC table. This method must be
- * used when the MAC is located in an External Device (TOR). The flow
- * matches on the specified MAC and 1) sends the packet over the CSS-TOR
- * tunnel if SHFlag is not set, or 2) drops it if SHFlag is set (what means
- * the packet came from an external tunnel)
- *
- * @param dpId
- * DPN whose DMAC table is going to be modified
- * @param extDeviceNodeId
- * Hwvtep node where the mac is attached to
- * @param elanTag
- * ElanId to which the MAC is being added to
- * @param vni
- * the vni
- * @param dstMacAddress
- * The mac address to be programmed
- * @param displayName
- * the display name
- * @return the flow
- * @throws ElanException in case of issues creating the flow objects
- */
- @SuppressWarnings("checkstyle:IllegalCatch")
- public Flow buildDmacFlowForExternalRemoteMac(BigInteger dpId, String extDeviceNodeId, long elanTag,
- Long vni, String dstMacAddress, String displayName) throws ElanException {
- List<MatchInfo> mkMatches = buildMatchesForElanTagShFlagAndDstMac(elanTag, /* shFlag */ false, dstMacAddress);
- List<Instruction> mkInstructions = new ArrayList<>();
- try {
- List<Action> actions = getExternalTunnelItmEgressAction(dpId, new NodeId(extDeviceNodeId), vni);
- mkInstructions.add(MDSALUtil.buildApplyActionsInstruction(actions));
- } catch (Exception e) {
- LOG.error("Could not get Egress Actions for DpId=" + dpId + ", externalNode=" + extDeviceNodeId, e);
- }
-
- Flow flow = MDSALUtil.buildFlowNew(NwConstants.ELAN_DMAC_TABLE,
- getKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, dpId, extDeviceNodeId, dstMacAddress, elanTag,
- false),
- 20, /* prio */
- displayName, 0, /* idleTimeout */
- 0, /* hardTimeout */
- ElanConstants.COOKIE_ELAN_KNOWN_DMAC.add(BigInteger.valueOf(elanTag)), mkMatches, mkInstructions);
-
- return flow;
- }
-
- /**
- * Builds the flow that drops the packet if it came through an external
- * tunnel, that is, if the Split-Horizon flag is set.
- *
- * @param dpnId
- * DPN whose DMAC table is going to be modified
- * @param extDeviceNodeId
- * Hwvtep node where the mac is attached to
- * @param elanTag
- * ElanId to which the MAC is being added to
- * @param dstMacAddress
- * The mac address to be programmed
- */
- private static Flow buildDmacFlowDropIfPacketComingFromTunnel(BigInteger dpnId, String extDeviceNodeId,
- Long elanTag, String dstMacAddress) {
- List<MatchInfo> mkMatches = buildMatchesForElanTagShFlagAndDstMac(elanTag, /* shFlag */ true, dstMacAddress);
- List<Instruction> mkInstructions = MDSALUtil.buildInstructionsDrop();
- String flowId = getKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, dpnId, extDeviceNodeId, dstMacAddress,
- elanTag, true);
- Flow flow = MDSALUtil.buildFlowNew(NwConstants.ELAN_DMAC_TABLE, flowId, 20, /* prio */
- "Drop", 0, /* idleTimeout */
- 0, /* hardTimeout */
- ElanConstants.COOKIE_ELAN_KNOWN_DMAC.add(BigInteger.valueOf(elanTag)), mkMatches, mkInstructions);
-
- return flow;
- }
-
- private static String getDmacDropFlowId(Long elanTag, String dstMacAddress) {
- return new StringBuilder(NwConstants.ELAN_DMAC_TABLE).append(elanTag).append(dstMacAddress).append("Drop")
- .toString();
- }
-
- /**
- * Installs or removes flows in DMAC table for MACs that are/were located in
- * an external Elan Device.
- *
- * @param dpId
- * Id of the DPN where the DMAC table is going to be modified
- * @param extNodeId
- * Id of the External Device where the MAC is located
- * @param elanTag
- * Id of the ELAN
- * @param vni
- * VNI of the LogicalSwitch to which the MAC belongs to, and that
- * is associated with the ELAN
- * @param macAddress
- * the mac address
- * @param elanInstanceName
- * the elan instance name
- * @param addOrRemove
- * Indicates if flows must be installed or removed.
- * @param interfaceName
- * the interface name
- * @throws ElanException in case of issues creating the flow objects
- * @see org.opendaylight.genius.mdsalutil.MDSALUtil.MdsalOp
- */
- public void setupDmacFlowsToExternalRemoteMac(BigInteger dpId, String extNodeId, Long elanTag, Long vni,
- String macAddress, String elanInstanceName, MdsalOp addOrRemove, String interfaceName)
- throws ElanException {
- if (addOrRemove == MdsalOp.CREATION_OP) {
- installDmacFlowsToExternalRemoteMac(dpId, extNodeId, elanTag, vni, macAddress, elanInstanceName,
- interfaceName);
- } else if (addOrRemove == MdsalOp.REMOVAL_OP) {
- deleteDmacFlowsToExternalMac(elanTag, dpId, extNodeId, macAddress);
- }
- }
-
- /**
- * Delete dmac flows to external mac.
- *
- * @param elanTag
- * the elan tag
- * @param dpId
- * the dp id
- * @param extDeviceNodeId
- * the ext device node id
- * @param macToRemove
- * the mac to remove
- * @return dmac flow
- */
- public List<ListenableFuture<Void>> deleteDmacFlowsToExternalMac(long elanTag, BigInteger dpId,
- String extDeviceNodeId, String macToRemove) {
- List<ListenableFuture<Void>> futures = new ArrayList<>();
- synchronized (getElanMacDPNKey(elanTag, macToRemove, dpId)) {
- // Removing the flows that sends the packet on an external tunnel
- removeFlowThatSendsThePacketOnAnExternalTunnel(elanTag, dpId, extDeviceNodeId, macToRemove, futures);
-
- // And now removing the drop flow
- removeTheDropFlow(elanTag, dpId, extDeviceNodeId, macToRemove, futures);
-
- deleteEtreeDmacFlowsToExternalMac(elanTag, dpId, extDeviceNodeId, macToRemove, futures);
- }
- return futures;
- }
-
- private void deleteEtreeDmacFlowsToExternalMac(long elanTag, BigInteger dpId, String extDeviceNodeId,
- String macToRemove, List<ListenableFuture<Void>> futures) {
- EtreeLeafTagName etreeLeafTag = getEtreeLeafTagByElanTag(elanTag);
- if (etreeLeafTag != null) {
- removeFlowThatSendsThePacketOnAnExternalTunnel(etreeLeafTag.getEtreeLeafTag().getValue(), dpId,
- extDeviceNodeId, macToRemove, futures);
- removeTheDropFlow(etreeLeafTag.getEtreeLeafTag().getValue(), dpId, extDeviceNodeId, macToRemove, futures);
- }
- }
-
- private void removeTheDropFlow(long elanTag, BigInteger dpId, String extDeviceNodeId, String macToRemove,
- List<ListenableFuture<Void>> futures) {
- String flowId = getKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, dpId, extDeviceNodeId, macToRemove,
- elanTag, true);
- Flow flowToRemove = new FlowBuilder().setId(new FlowId(flowId)).setTableId(NwConstants.ELAN_DMAC_TABLE).build();
- futures.add(mdsalManager.removeFlow(dpId, flowToRemove));
- }
-
- private void removeFlowThatSendsThePacketOnAnExternalTunnel(long elanTag, BigInteger dpId,
- String extDeviceNodeId, String macToRemove, List<ListenableFuture<Void>> futures) {
- String flowId = getKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, dpId, extDeviceNodeId, macToRemove,
- elanTag, false);
- Flow flowToRemove = new FlowBuilder().setId(new FlowId(flowId)).setTableId(NwConstants.ELAN_DMAC_TABLE).build();
- futures.add(mdsalManager.removeFlow(dpId, flowToRemove));
- }
-
- /**
- * Gets the dpid from interface.
- *
- * @param interfaceName
- * the interface name
- * @return the dpid from interface
- */
- public BigInteger getDpidFromInterface(String interfaceName) {
- BigInteger dpId = null;
- Future<RpcResult<GetDpidFromInterfaceOutput>> output = interfaceManagerRpcService
- .getDpidFromInterface(new GetDpidFromInterfaceInputBuilder().setIntfName(interfaceName).build());
- try {
- RpcResult<GetDpidFromInterfaceOutput> rpcResult = output.get();
- if (rpcResult.isSuccessful()) {
- dpId = rpcResult.getResult().getDpid();
- }
- } catch (NullPointerException | InterruptedException | ExecutionException e) {
- LOG.error("Failed to get the DPN ID: {} for interface {}: {} ", dpId, interfaceName, e);
- }
- return dpId;
- }
-