/* * Copyright (c) 2013 Ericsson AB. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html * */ package org.opendaylight.vpnservice.mdsalutil.internal; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import org.opendaylight.controller.md.sal.common.api.TransactionStatus; //import org.opendaylight.controller.md.sal.common.api.data.DataModification; import org.opendaylight.vpnservice.mdsalutil.ActionInfo; import org.opendaylight.vpnservice.mdsalutil.ActionType; import org.opendaylight.vpnservice.mdsalutil.BucketInfo; import org.opendaylight.vpnservice.mdsalutil.FlowEntity; import org.opendaylight.vpnservice.mdsalutil.GroupEntity; import org.opendaylight.vpnservice.mdsalutil.InstructionInfo; import org.opendaylight.vpnservice.mdsalutil.MDSALUtil; import org.opendaylight.vpnservice.mdsalutil.MatchInfo; import org.opendaylight.vpnservice.mdsalutil.MatchFieldType; import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil; import org.opendaylight.vpnservice.mdsalutil.InstructionType; import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext; import org.opendaylight.controller.sal.binding.api.BindingAwareConsumer; import org.opendaylight.controller.sal.binding.api.data.DataBrokerService; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowTableRef; // Missing constraint //import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef; import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId; import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group; import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; //import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.OpendaylightInventoryService; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder; import org.opendaylight.yangtools.yang.common.RpcResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; import com.google.common.util.concurrent.CheckedFuture; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; public class MDSALManager implements IMdsalApiManager,BindingAwareConsumer, AutoCloseable { private static final Logger s_logger = LoggerFactory.getLogger(MDSALManager.class); private DataBroker m_dataBroker; private ConsumerContext m_consumerContext = null; private PacketProcessingService m_packetProcessingService; private final AtomicInteger m_atomicInteger = new AtomicInteger(); //TODO : IF ID MANAGER IS RQD @Override public void onSessionInitialized(ConsumerContext session) { s_logger.info( " Session Initiated for MD SAL Manager") ; m_consumerContext = session; m_dataBroker = session.getSALService(DataBroker.class); // TODO - Verify this. m_packetProcessingService = session.getRpcService(PacketProcessingService.class); } @Override public void close() throws Exception { s_logger.info("MDSAL Manager Closed"); } @Override public void printTest() { s_logger.info(" INTER MODULECOMMUNICATION IS WORKING!!!!"); } @Override public void installFlow(FlowEntity flowEntity) { try { s_logger.info("within installFlowX {}", flowEntity.getDpnId()); System.out.println( " Insie installFlow -- ") ; if (flowEntity.getCookie() == null) { s_logger.info("Helium_sync: Cookie is null"); flowEntity.setCookie(new BigInteger("0110000", 16)); } Flow flow = flowEntity.getFlowBuilder().build(); Node nodeDpn = buildDpnNode(flowEntity.getDpnId()); InstanceIdentifier nodeInstanceId = InstanceIdentifier.builder(Nodes.class) .child(Node.class, nodeDpn.getKey()).build(); InstanceIdentifier flowInstanceId = InstanceIdentifier.builder(Nodes.class) .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class) .child(Table.class, new TableKey(flow.getTableId())).child(Flow.class, flow.getKey()).build(); String sTransactionUri = generateTransactionUri(); // Helium Way WriteTransaction modification = m_dataBroker.newWriteOnlyTransaction(); modification.put(LogicalDatastoreType.CONFIGURATION, nodeInstanceId, nodeDpn, true); modification.put(LogicalDatastoreType.CONFIGURATION, flowInstanceId, flow); ListenableFuture> commitFuture = modification.commit(); Futures.addCallback(commitFuture, new FutureCallback>() { @Override public void onSuccess(RpcResult result) { if( result.getResult() != TransactionStatus.COMMITED ) { s_logger.debug("Failed to commit the Flow Data " + result.getErrors()); } } @Override public void onFailure(Throwable throwable) { s_logger.error(throwable.getMessage(), throwable); s_logger.debug(String.format("Status of Flow Data Loaded Transaction : failure. Reason : %s", throwable)); } }); } catch (Exception e) { s_logger.error("Could not install flow: {}, exception: {}", flowEntity, e.getMessage()); } } @Override public void installGroup(GroupEntity groupEntity) { try { Group group = groupEntity.getGroupBuilder().build(); Node nodeDpn = buildDpnNode(groupEntity.getDpnId()); InstanceIdentifier nodeInstanceId = InstanceIdentifier.builder(Nodes.class) .child(Node.class, nodeDpn.getKey()).build(); InstanceIdentifier groupInstanceId = InstanceIdentifier.builder(Nodes.class) .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class) .child(Group.class, new GroupKey(new GroupId(groupEntity.getGroupId()))).build(); // Helium WriteTransaction modification = m_dataBroker.newWriteOnlyTransaction(); modification.put(LogicalDatastoreType.CONFIGURATION, nodeInstanceId, nodeDpn); modification.put(LogicalDatastoreType.CONFIGURATION, groupInstanceId, group); ListenableFuture> commitFuture = modification.commit(); Futures.addCallback(commitFuture, new FutureCallback>() { @Override public void onSuccess(RpcResult result) { if( result.getResult() != TransactionStatus.COMMITED ) { s_logger.debug("Failed to commit the group Data " + result.getErrors()); } } @Override public void onFailure(Throwable throwable) { s_logger.error(throwable.getMessage(), throwable); s_logger.debug(String.format("Status of Group Data Loaded Transaction : failure. Reason : %s", throwable)); } }); } catch (Exception e) { s_logger.error("Could not install Group: {}, exception: {}", groupEntity, e.getMessage()); throw e; } } @Override public void removeFlow(FlowEntity flowEntity) { try { Node nodeDpn = buildDpnNode(flowEntity.getDpnId()); FlowKey flowKey = new FlowKey(new FlowId(flowEntity.getFlowId())); InstanceIdentifier flowInstanceId = InstanceIdentifier.builder(Nodes.class) .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class) .child(Table.class, new TableKey(flowEntity.getTableId())).child(Flow.class, flowKey).build(); WriteTransaction modification = m_dataBroker.newWriteOnlyTransaction(); modification.delete(LogicalDatastoreType.CONFIGURATION,flowInstanceId ); ListenableFuture> commitFuture = modification.commit(); Futures.addCallback(commitFuture, new FutureCallback>() { @Override public void onSuccess(RpcResult result) { if( result.getResult() != TransactionStatus.COMMITED ) { s_logger.debug("Failed to remove the Flow Data " + result.getErrors()); } } @Override public void onFailure(Throwable throwable) { s_logger.error(throwable.getMessage(), throwable); s_logger.debug(String.format("Status of Flow Data remove Transaction : failure. Reason : %s", throwable)); } }); } catch (Exception e) { s_logger.error("Could not remove Flow: {}, exception: {}", flowEntity, e.getMessage()); } } @Override public void removeGroup(GroupEntity groupEntity) { try { Node nodeDpn = buildDpnNode(groupEntity.getDpnId()); InstanceIdentifier groupInstanceId = InstanceIdentifier.builder(Nodes.class) .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class) .child(Group.class, new GroupKey(new GroupId(groupEntity.getGroupId()))).build(); WriteTransaction modification = m_dataBroker.newWriteOnlyTransaction(); modification.delete(LogicalDatastoreType.CONFIGURATION,groupInstanceId ); ListenableFuture> commitFuture = modification.commit(); Futures.addCallback(commitFuture, new FutureCallback>() { @Override public void onSuccess(RpcResult result) { if( result.getResult() != TransactionStatus.COMMITED ) { s_logger.debug("Failed to remove the group Data " + result.getErrors()); } } @Override public void onFailure(Throwable throwable) { s_logger.error(throwable.getMessage(), throwable); s_logger.debug(String.format("Status of group Data remove Transaction : failure. Reason : %s", throwable)); } }); } catch (Exception e) { s_logger.error("Could not remove Group: {}, exception: {}", groupEntity, e.getMessage()); } } @Override public void modifyGroup(GroupEntity groupEntity) { installGroup(groupEntity); } private String generateTransactionUri() { long lTransactionIdOut = m_atomicInteger.incrementAndGet(); // TO DO Introduce this later // return "" + (lTransactionIdOut | m_lTransactionIdPrefix); return "" + (lTransactionIdOut ); } /* private String generateTransactionUriForFlow(long nTransactionId) { long lTransactionIdOut = m_atomicInteger.incrementAndGet(); return Long.toString((lTransactionIdOut | m_lTransactionIdPrefix)) + EUtil.TRANSACTION_ID_SEPARATOR + Long.toString(nTransactionId); } */ @Override public void sendPacketOut(long lDpnId, int groupId, byte[] payload) { List actionInfos = new ArrayList(); actionInfos.add(new ActionInfo(ActionType.group, new String[] { String.valueOf(groupId) })); sendPacketOutWithActions(lDpnId, groupId, payload, actionInfos); } @Override public void sendPacketOutWithActions(long lDpnId, long groupId, byte[] payload, List actionInfos) { m_packetProcessingService.transmitPacket(MDSALUtil.getPacketOut(actionInfos, payload, lDpnId, getNodeConnRef("openflow:" + lDpnId, "0xfffffffd"))); } @Override public void sendARPPacketOutWithActions(long lDpnId, byte[] payload, List actions) { m_packetProcessingService.transmitPacket(MDSALUtil.getPacketOut(actions, payload, lDpnId, getNodeConnRef("openflow:" + lDpnId, "0xfffffffd"))); } private NodeKey getNodeKey(long dpId) { String nodeId = "openflow:" + dpId; NodeKey nodeKey = new NodeKey(new NodeId(nodeId)); return nodeKey; } public InstanceIdentifier nodeToInstanceId(Node node) { return InstanceIdentifier.builder(Nodes.class).child(Node.class, node.getKey()).toInstance(); } private static NodeConnectorRef getNodeConnRef(final String nodeId, final String port) { StringBuilder _stringBuilder = new StringBuilder(nodeId); StringBuilder _append = _stringBuilder.append(":"); StringBuilder sBuild = _append.append(port); String _string = sBuild.toString(); NodeConnectorId _nodeConnectorId = new NodeConnectorId(_string); NodeConnectorKey _nodeConnectorKey = new NodeConnectorKey(_nodeConnectorId); NodeConnectorKey nConKey = _nodeConnectorKey; InstanceIdentifierBuilder _builder = InstanceIdentifier. builder(Nodes.class); NodeId _nodeId = new NodeId(nodeId); NodeKey _nodeKey = new NodeKey(_nodeId); InstanceIdentifierBuilder _child = _builder. child(Node.class, _nodeKey); InstanceIdentifierBuilder _child_1 = _child. child( NodeConnector.class, nConKey); InstanceIdentifier path = _child_1.toInstance(); NodeConnectorRef _nodeConnectorRef = new NodeConnectorRef(path); return _nodeConnectorRef; } private long getDpnIdFromNodeName(String nodeName) { String dpId = nodeName.substring(nodeName.lastIndexOf(":") + 1); return Long.parseLong(dpId); } private Node buildDpnNode(long lDpnId) { NodeId nodeId = new NodeId("openflow:" + lDpnId); Node nodeDpn = new NodeBuilder().setId(nodeId).setKey(new NodeKey(nodeId)).build(); return nodeDpn; } }