2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.openflowplugin.openflow.md.core.sal.convertor;
10 import com.google.common.collect.Iterables;
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.Collections;
14 import java.util.List;
16 import java.util.Optional;
18 import org.opendaylight.controller.sal.common.util.Arguments;
19 import org.opendaylight.openflowplugin.api.OFConstants;
20 import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
21 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.action.data.ActionConvertorData;
22 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.Convertor;
23 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.XidConvertorData;
24 import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.action.grouping.action.choice.OutputActionCaseBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.action.grouping.action.choice.output.action._case.OutputActionBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions.grouping.Action;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions.grouping.ActionBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortNumber;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketOutInput;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketOutInputBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
35 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
36 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
37 import org.opendaylight.yangtools.yang.common.Uint32;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
42 * Converts a MD-SAL packet out data into the OF library packet out input.
48 * XidConvertorData data = new XidConvertorData(version);
49 * data.setDatapathId(datapathId);
51 * Optional<PacketOutInput> ofPacketInput = convertorManager.convert(salPacket, data);
55 public class PacketOutConvertor extends Convertor<TransmitPacketInput, PacketOutInput, XidConvertorData> {
56 private static final Logger LOG = LoggerFactory.getLogger(PacketOutConvertor.class);
57 private static final Set<Class<?>> TYPES = Collections.singleton(TransmitPacketInput.class);
58 private static final PortNumber CONTROLLER_PORT = new PortNumber(Uint32.valueOf(0xfffffffdL).intern());
61 * Create default empty meter mot input builder.
62 * Use this method, if result from convertor is empty.
64 * @param version Openflow version
65 * @return default empty meter mod input builder
67 public static PacketOutInput defaultResult(final short version) {
68 return new PacketOutInputBuilder()
73 private static PortNumber getPortNumber(final PathArgument pathArgument, final Short ofVersion) {
74 // FIXME VD P! find InstanceIdentifier helper
75 InstanceIdentifier.IdentifiableItem<?, ?> item = Arguments.checkInstanceOf(pathArgument,
76 InstanceIdentifier.IdentifiableItem.class);
77 NodeConnectorKey key = Arguments.checkInstanceOf(item.getKey(), NodeConnectorKey.class);
78 Uint32 port = InventoryDataServiceUtil.portNumberfromNodeConnectorId(
79 OpenflowVersion.get(ofVersion), key.getId());
80 return new PortNumber(port);
84 public Collection<Class<?>> getTypes() {
89 public PacketOutInput convert(final TransmitPacketInput source, final XidConvertorData data) {
90 LOG.trace("toPacketOutInput for datapathId:{}, xid:{}", data.getDatapathId(), data.getXid());
91 // Build Port ID from TransmitPacketInput.Ingress
93 Uint32 bufferId = OFConstants.OFP_NO_BUFFER;
94 Iterable<PathArgument> inArgs = null;
96 if (source.getIngress() != null) {
97 inArgs = source.getIngress().getValue().getPathArguments();
100 if (inArgs != null && Iterables.size(inArgs) >= 3) {
101 inPortNr = getPortNumber(Iterables.get(inArgs, 2), data.getVersion());
103 // The packetOut originated from the controller
104 inPortNr = CONTROLLER_PORT;
107 // Build Buffer ID to be NO_OFP_NO_BUFFER
108 if (source.getBufferId() != null) {
109 bufferId = source.getBufferId();
112 PortNumber outPort = null;
113 NodeConnectorRef outRef = source.getEgress();
114 Iterable<PathArgument> outArgs = outRef.getValue().getPathArguments();
116 if (Iterables.size(outArgs) >= 3) {
117 outPort = getPortNumber(Iterables.get(outArgs, 2), data.getVersion());
119 // TODO : P4 search for some normal exception
120 // new Exception("PORT NR not exist in Egress");
121 LOG.error("PORT NR not exist in Egress");
124 final List<Action> actions;
125 Map<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey,
126 org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> inputActions =
127 source.nonnullAction();
129 if (!inputActions.isEmpty()) {
130 final ActionConvertorData actionConvertorData = new ActionConvertorData(data.getVersion());
131 actionConvertorData.setDatapathId(data.getDatapathId());
133 final Optional<List<Action>> convertedActions = getConvertorExecutor().convert(
134 inputActions, actionConvertorData);
136 actions = convertedActions.orElse(Collections.emptyList());
139 // TODO VD P! wait for way to move Actions (e.g. augmentation)
140 OutputActionCaseBuilder outputActionCaseBuilder = new OutputActionCaseBuilder();
141 OutputActionBuilder outputActionBuilder = new OutputActionBuilder();
142 outputActionBuilder.setPort(outPort);
143 outputActionBuilder.setMaxLength(OFConstants.OFPCML_NO_BUFFER);
144 outputActionCaseBuilder.setOutputAction(outputActionBuilder.build());
145 ActionBuilder actionBuild = new ActionBuilder();
146 actionBuild.setActionChoice(outputActionCaseBuilder.build());
147 actions = new ArrayList<>();
148 actions.add(actionBuild.build());
151 PacketOutInputBuilder builder = new PacketOutInputBuilder();
152 builder.setAction(actions);
153 builder.setData(source.getPayload());
154 builder.setVersion(data.getVersion());
155 builder.setXid(data.getXid());
156 builder.setInPort(inPortNr);
157 builder.setBufferId(bufferId);
159 return builder.build();