/* * Copyright (c) 2016 NEC Corporation and others. 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.nic.of.renderer.impl; import java.util.List; import com.google.common.base.Optional; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.nic.of.renderer.utils.MatchUtils; import org.opendaylight.nic.pipeline_manager.PipelineManager; import org.opendaylight.nic.utils.FlowAction; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Dscp; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress; 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.FlowBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.OutputPortValues; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.actions.Action; import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.actions.action.Allow; import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.constraints.Constraints; import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.constraints.constraints.QosConstraint; import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.qos.config.Qos; import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.qos.config.qos.DscpType; import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intents.Intent; import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.Intents; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import com.google.common.base.Optional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class QosConstraintManager extends AbstractFlowManager { private static final Logger LOG = LoggerFactory.getLogger(QosConstraintManager.class); /** * The list of EndPointGroups. */ private List<String> endPointGroups = null; /** * The instance for Action. */ private Action action = null; /** * The instance for Constraints. */ private Constraints constraint = null; /** * The Constraint profile name. */ private String qosName = null; /** * Set the EndPointGroups. * @param endPointGroups : Source and destination end points */ public void setEndPointGroups(List<String> endPointGroups) { this.endPointGroups = endPointGroups; } /** * Set the Action. * @param action : Set the flow action */ public void setAction(Action action) { this.action = action; } /** * Set the Constraints. * @param constraint : Set the QoS constraints */ public void setConstraint(Constraints constraint) { this.constraint = constraint; } /** * Set the Constraint profile name. * @param qosName : Set the QoS name */ public void setQosName(String qosName) { this.qosName = qosName; } public static final InstanceIdentifier<Intents> INTENTS_IID = InstanceIdentifier.builder(Intents.class).build(); /** * Construct a new instance that matches the given DataBroker and PipelineManager. * * @param dataBroker DataBroker. * @param pipelineManager PipelineManager. */ public QosConstraintManager(DataBroker dataBroker, PipelineManager pipelineManager) { super(dataBroker, pipelineManager); } /** * Set the flow for action and constraints. */ @Override public void pushFlow(NodeId nodeId, FlowAction flowAction) { if (endPointGroups == null || action == null) { LOG.error("Endpoints and action cannot be null"); return; } // Creating match object MatchBuilder matchBuilder = new MatchBuilder(); // Creating Flow object FlowBuilder flowBuilder = new FlowBuilder(); // Create L2 match createEthMatch(endPointGroups, matchBuilder); // Create Flow flowBuilder = createFlowBuilder(matchBuilder); if (action instanceof Allow && constraint instanceof QosConstraint) { List<Intent> intentList = listIntents(); for (Intent intentValue : intentList) { if (intentValue.getQosConfig() != null) { Qos qosContainer = (Qos) intentValue.getQosConfig().get(0).getQos(); if (((DscpType) qosContainer).getDscpType().getName() != null) { String profileNames = ((DscpType) qosContainer).getDscpType().getName(); Dscp dscpValues = ((DscpType) qosContainer).getDscpType().getDscp(); LOG.debug("Profile Name: {} and DSCP Value: {}", profileNames, dscpValues); if (profileNames.equalsIgnoreCase(qosName)) { LOG.trace("Profile name: {} and QoS Constraint Name: {} is a match", profileNames, qosName); Instructions buildedInstructions = createQoSInstructions(dscpValues, OutputPortValues.NORMAL); flowBuilder.setInstructions(buildedInstructions); writeDataTransaction(nodeId, flowBuilder, flowAction); return; } } } } LOG.error("Please fill the QoS Configuration profile."); } else { String actionClass = action.getClass().getName(); LOG.error("Invalid action: {}", actionClass); return; } } private FlowBuilder createFlowBuilder(MatchBuilder matchBuilder) { final Match match = matchBuilder.build(); // Flow named for convenience and uniqueness String flowName = createFlowName(); final FlowId flowId = new FlowId(flowName); final FlowKey key = new FlowKey(flowId); final FlowBuilder flowBuilder = new FlowBuilder(); flowBuilder.setMatch(match); flowBuilder.setId(flowId); flowBuilder.setKey(key); flowBuilder.setBarrier(true); flowBuilder.setPriority(OFRendererConstants.DEFAULT_PRIORITY); flowBuilder.setFlowName(flowName); flowBuilder.setHardTimeout(OFRendererConstants.DEFAULT_HARD_TIMEOUT); flowBuilder.setIdleTimeout(OFRendererConstants.DEFAULT_IDLE_TIMEOUT); return flowBuilder; } private void createEthMatch(List<String> endPointGroups, MatchBuilder matchBuilder) { String endPointSrc = endPointGroups.get(OFRendererConstants.SRC_END_POINT_GROUP_INDEX); String endPointDst = endPointGroups.get(OFRendererConstants.DST_END_POINT_GROUP_INDEX); MacAddress srcMac = null; MacAddress dstMac = null; LOG.info("Creating intent for endpoints: source{} destination {}", endPointSrc, endPointDst); try { if (!endPointSrc.equalsIgnoreCase(OFRendererConstants.ANY_MATCH)) { srcMac = new MacAddress(endPointSrc); } if (!endPointDst.equalsIgnoreCase(OFRendererConstants.ANY_MATCH)) { dstMac = new MacAddress(endPointDst); } MatchUtils.createEthMatch(matchBuilder, srcMac, dstMac); } catch (IllegalArgumentException e) { LOG.error("Can only accept valid MAC addresses as subjects", e); } } @Override protected String createFlowName() { StringBuilder sb = new StringBuilder(); sb.append(OFRendererConstants.INTENT_L2_FLOW_NAME); sb.append(endPointGroups.get(OFRendererConstants.SRC_END_POINT_GROUP_INDEX)); sb.append(endPointGroups.get(OFRendererConstants.DST_END_POINT_GROUP_INDEX)); return sb.toString(); } /** * Gets the list of intents from the Data store. * @return list of intents. */ private List<Intent> listIntents() { List<Intent> listOfIntents = null; try { ReadOnlyTransaction tx = dataBroker.newReadOnlyTransaction(); Optional<Intents> intents = tx.read((true) ? LogicalDatastoreType.CONFIGURATION : LogicalDatastoreType.OPERATIONAL, INTENTS_IID).checkedGet(); if(intents.isPresent()) { listOfIntents = intents.get().getIntent(); } else { LOG.info("Intent tree was empty!"); } } catch (Exception e) { LOG.error("ListIntents: failed: {}", e.getMessage(), e); } return listOfIntents; } }