Bug 5540 - ActionConvertor, ActionResponseConvertor
[openflowplugin.git] / openflowplugin / src / main / java / org / opendaylight / openflowplugin / openflow / md / core / sal / convertor / PacketOutConvertor.java
1 /**
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.openflowplugin.openflow.md.core.sal.convertor;
9
10 import com.google.common.collect.Iterables;
11 import java.math.BigInteger;
12 import java.util.ArrayList;
13 import java.util.Collections;
14 import java.util.List;
15 import java.util.Optional;
16 import org.opendaylight.controller.sal.common.util.Arguments;
17 import org.opendaylight.openflowplugin.api.OFConstants;
18 import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
19 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.action.data.ActionConvertorData;
20 import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.action.grouping.action.choice.OutputActionCaseBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.action.grouping.action.choice.output.action._case.OutputActionBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions.grouping.Action;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions.grouping.ActionBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortNumber;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketOutInput;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketOutInputBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
31 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
32 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 public final class PacketOutConvertor {
37     private static final Logger LOG = LoggerFactory.getLogger(PacketOutConvertor.class);
38
39     private PacketOutConvertor() {
40
41     }
42
43     // Get all the data for the PacketOut from the Yang/SAL-Layer
44
45     /**
46      * @param version openflow version
47      * @param inputPacket input packet
48      * @param datapathid  datapath id
49      * @param xid tx id
50      * @return PacketOutInput required by OF Library
51      */
52     public static PacketOutInput toPacketOutInput(final TransmitPacketInput inputPacket, final short version, final Long xid,
53                                                   final BigInteger datapathid) {
54
55         LOG.trace("toPacketOutInput for datapathId:{}, xid:{}", datapathid, xid);
56         // Build Port ID from TransmitPacketInput.Ingress
57         PortNumber inPortNr = null;
58         Long bufferId = OFConstants.OFP_NO_BUFFER;
59         Iterable<PathArgument> inArgs = null;
60         PacketOutInputBuilder builder = new PacketOutInputBuilder();
61         if (inputPacket.getIngress() != null) {
62             inArgs = inputPacket.getIngress().getValue().getPathArguments();
63         }
64         if (inArgs != null && Iterables.size(inArgs) >= 3) {
65             inPortNr = getPortNumber(Iterables.get(inArgs, 2), version);
66         } else {
67             // The packetOut originated from the controller
68             inPortNr = new PortNumber(0xfffffffdL);
69         }
70
71         // Build Buffer ID to be NO_OFP_NO_BUFFER
72         if (inputPacket.getBufferId() != null) {
73             bufferId = inputPacket.getBufferId();
74         }
75
76         PortNumber outPort = null;
77         NodeConnectorRef outRef = inputPacket.getEgress();
78         Iterable<PathArgument> outArgs = outRef.getValue().getPathArguments();
79         if (Iterables.size(outArgs) >= 3) {
80             outPort = getPortNumber(Iterables.get(outArgs, 2), version);
81         } else {
82             // TODO : P4 search for some normal exception
83             new Exception("PORT NR not exist in Egress");
84         }
85
86         List<Action> actions = null;
87         List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> inputActions =
88                 inputPacket.getAction();
89         if (inputActions != null) {
90             final ActionConvertorData actionConvertorData = new ActionConvertorData(version);
91             actionConvertorData.setDatapathId(datapathid);
92
93             final Optional<List<Action>> convertedActions = ConvertorManager.getInstance().convert(
94                     inputActions, actionConvertorData);
95
96             actions = convertedActions.orElse(Collections.emptyList());
97
98         } else {
99             actions = new ArrayList<>();
100             // TODO VD P! wait for way to move Actions (e.g. augmentation)
101             ActionBuilder aBuild = new ActionBuilder();
102
103             OutputActionCaseBuilder outputActionCaseBuilder =
104                     new OutputActionCaseBuilder();
105
106             OutputActionBuilder outputActionBuilder =
107                     new OutputActionBuilder();
108
109             outputActionBuilder.setPort(outPort);
110             outputActionBuilder.setMaxLength(OFConstants.OFPCML_NO_BUFFER);
111
112             outputActionCaseBuilder.setOutputAction(outputActionBuilder.build());
113
114             aBuild.setActionChoice(outputActionCaseBuilder.build());
115
116             actions.add(aBuild.build());
117         }
118
119         builder.setAction(actions);
120         builder.setData(inputPacket.getPayload());
121         builder.setVersion(version);
122         builder.setXid(xid);
123         builder.setInPort(inPortNr);
124         builder.setBufferId(bufferId);
125         // --------------------------------------------------------
126
127         return builder.build();
128     }
129
130     private static PortNumber getPortNumber(final PathArgument pathArgument, final Short ofVersion) {
131         // FIXME VD P! find InstanceIdentifier helper
132         InstanceIdentifier.IdentifiableItem<?, ?> item = Arguments.checkInstanceOf(pathArgument,
133                 InstanceIdentifier.IdentifiableItem.class);
134         NodeConnectorKey key = Arguments.checkInstanceOf(item.getKey(), NodeConnectorKey.class);
135         Long port =  InventoryDataServiceUtil.portNumberfromNodeConnectorId(
136                 OpenflowVersion.get(ofVersion), key.getId());
137         return new PortNumber(port);
138     }
139 }