/* * Copyright © 2015 Red Hat, Inc. 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.ovsdb.openstack.netvirt.sfc.workaround.services; import com.google.common.collect.Lists; import java.math.BigInteger; import java.util.List; import org.opendaylight.ovsdb.openstack.netvirt.providers.ConfigInterface; import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance; import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service; import org.opendaylight.ovsdb.openstack.netvirt.sfc.ISfcClassifierService; import org.opendaylight.ovsdb.openstack.netvirt.sfc.NshUtils; import org.opendaylight.ovsdb.utils.mdsal.openflow.ActionUtils; import org.opendaylight.ovsdb.utils.mdsal.openflow.FlowUtils; import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.Matches; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.matches.ace.type.AceEth; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIp; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv4; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey; 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.flow.InstructionsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class SfcClassifierService extends AbstractServiceInstance implements ConfigInterface, ISfcClassifierService { private static final Logger LOG = LoggerFactory.getLogger(SfcClassifierService.class); private static final short SFC_TABLE = 10; public SfcClassifierService(Service service) { super(service); } public SfcClassifierService() { super(Service.SFC_CLASSIFIER); } @Override public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) { super.setDependencies(bundleContext.getServiceReference(ISfcClassifierService.class.getName()), this); } @Override public void setDependencies(Object impl) {} @Override public void programIngressClassifier(long dataPathId, String ruleName, Matches matches, NshUtils nshHeader, long vxGpeOfPort, boolean write) { NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId); FlowBuilder flowBuilder = new FlowBuilder(); MatchBuilder matchBuilder = buildMatch(matches); flowBuilder.setMatch(matchBuilder.build()); MatchUtils.addNxRegMatch(matchBuilder, new MatchUtils.RegMatch(FlowUtils.REG_FIELD, FlowUtils.REG_VALUE_FROM_LOCAL)); String flowId = "sfcClass_" + ruleName;// + "_" + nshHeader.getNshNsp(); flowBuilder.setId(new FlowId(flowId)); FlowKey key = new FlowKey(new FlowId(flowId)); flowBuilder.setBarrier(true); flowBuilder.setTableId(SFC_TABLE); flowBuilder.setKey(key); flowBuilder.setFlowName(flowId); flowBuilder.setHardTimeout(0); flowBuilder.setIdleTimeout(0); if (write) { List actionList = getNshAction(nshHeader); ActionBuilder ab = new ActionBuilder(); ab.setAction(ActionUtils.outputAction(FlowUtils.getNodeConnectorId(dataPathId, vxGpeOfPort))); ab.setOrder(actionList.size()); ab.setKey(new ActionKey(actionList.size())); actionList.add(ab.build()); ApplyActionsBuilder aab = new ApplyActionsBuilder(); aab.setAction(actionList); InstructionBuilder ib = new InstructionBuilder(); ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build()); ib.setOrder(0); ib.setKey(new InstructionKey(0)); List instructions = Lists.newArrayList(); instructions.add(ib.build()); InstructionsBuilder isb = new InstructionsBuilder(); isb.setInstruction(instructions); flowBuilder.setInstructions(isb.build()); writeFlow(flowBuilder, nodeBuilder); } else { removeFlow(flowBuilder, nodeBuilder); } } private List getNshAction(NshUtils header) { // Build the Actions to Add the NSH Header org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action nshC1Load = ActionUtils.nxLoadNshc1RegAction(header.getNshMetaC1()); org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action nshC2Load = ActionUtils.nxLoadNshc2RegAction(header.getNshMetaC2()); org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action nspLoad = ActionUtils.nxSetNspAction(header.getNshNsp()); org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action nsiLoad = ActionUtils.nxSetNsiAction(header.getNshNsi()); org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action loadChainTunVnid = ActionUtils.nxLoadTunIdAction(BigInteger.valueOf(header.getNshNsp()), false); org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action loadChainTunDest = ActionUtils.nxLoadTunIPv4Action(header.getNshTunIpDst().getValue(), false); int count = 0; List actionList = Lists.newArrayList(); actionList.add(new ActionBuilder().setOrder(count++).setAction(nshC1Load).build()); actionList.add(new ActionBuilder().setOrder(count++).setAction(nshC2Load).build()); actionList.add(new ActionBuilder().setOrder(count++).setAction(nspLoad).build()); actionList.add(new ActionBuilder().setOrder(count++).setAction(nsiLoad).build()); actionList.add(new ActionBuilder().setOrder(count++).setAction(loadChainTunDest).build()); actionList.add(new ActionBuilder().setOrder(count++).setAction(loadChainTunVnid).build()); return actionList; } public MatchBuilder buildMatch(Matches matches) { MatchBuilder matchBuilder = new MatchBuilder(); if (matches.getAceType() instanceof AceIp) { AceIp aceIp = (AceIp)matches.getAceType(); if (aceIp.getAceIpVersion() instanceof AceIpv4) { //AceIpv4 aceIpv4 = (AceIpv4) aceIp.getAceIpVersion(); //MatchUtils.createSrcL3IPv4Match(matchBuilder, aceIpv4.getSourceIpv4Network()); //MatchUtils.createDstL3IPv4Match(matchBuilder, aceIpv4.getDestinationIpv4Network()); MatchUtils.createIpProtocolMatch(matchBuilder, aceIp.getProtocol()); MatchUtils.addLayer4Match(matchBuilder, aceIp.getProtocol().intValue(), 0, aceIp.getDestinationPortRange().getLowerPort().getValue().intValue()); } } else if (matches.getAceType() instanceof AceEth) { AceEth aceEth = (AceEth) matches.getAceType(); MatchUtils.createEthSrcMatch(matchBuilder, new MacAddress(aceEth.getSourceMacAddress().getValue())); MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(aceEth.getDestinationMacAddress().getValue()), new MacAddress(aceEth.getDestinationMacAddressMask().getValue())); } LOG.info("buildMatch: {}", matchBuilder.build()); return matchBuilder; } }