Merge "Replace odl-dlux-core with odl-dluxapps-topology"
[openflowplugin.git] / extension / openflowjava-extension-nicira / src / main / java / org / opendaylight / openflowjava / nx / codec / action / ConntrackCodec.java
1 /*
2  * Copyright (c) 2015, 2017 Hewlett-Packard Enterprise 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
9 package org.opendaylight.openflowjava.nx.codec.action;
10
11 import io.netty.buffer.ByteBuf;
12
13 import java.net.InetAddress;
14 import java.util.ArrayList;
15 import java.util.List;
16
17 import org.opendaylight.openflowjava.nx.api.NiciraActionDeserializerKey;
18 import org.opendaylight.openflowjava.nx.api.NiciraActionSerializerKey;
19 import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions.grouping.Action;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions.grouping.ActionBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.NxActionNatRangePresent;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionConntrack;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionConntrackBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.conntrack.grouping.NxActionConntrackBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.conntrack.grouping.nx.action.conntrack.CtActions;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.conntrack.grouping.nx.action.conntrack.CtActionsBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofpact.actions.ofpact.actions.NxActionNatCase;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofpact.actions.ofpact.actions.NxActionNatCaseBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofpact.actions.ofpact.actions.nx.action.nat._case.NxActionNat;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofpact.actions.ofpact.actions.nx.action.nat._case.NxActionNatBuilder;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 import com.google.common.net.InetAddresses;
38
39 /**
40  * @author Aswin Suryanarayanan.
41  */
42
43 public class ConntrackCodec extends AbstractActionCodec {
44     private static final Logger LOG = LoggerFactory.getLogger( ConntrackCodec.class);
45     public static final int CT_LENGTH = 24;
46     public static final int NX_NAT_LENGTH = 16;
47     public static final int SHORT_LENGTH = 2;
48     public static final int INT_LENGTH = 4;
49
50     public static final byte NXAST_CONNTRACK_SUBTYPE = 35;
51     public static final byte NXAST_NAT_SUBTYPE = 36;
52     public static final NiciraActionSerializerKey SERIALIZER_KEY =
53             new NiciraActionSerializerKey(EncodeConstants.OF13_VERSION_ID, ActionConntrack.class);
54     public static final NiciraActionDeserializerKey DESERIALIZER_KEY =
55             new NiciraActionDeserializerKey(EncodeConstants.OF13_VERSION_ID, NXAST_CONNTRACK_SUBTYPE);
56
57     @Override
58     public void serialize(final Action input, final ByteBuf outBuffer) {
59         LOG.trace("serialize :conntrack");
60         ActionConntrack action = (ActionConntrack) input.getActionChoice();
61         int length = getActionLength(action);
62         int pad = length % 8;
63         serializeHeader(length + pad + CT_LENGTH, NXAST_CONNTRACK_SUBTYPE, outBuffer);
64
65         outBuffer.writeShort(action.getNxActionConntrack().getFlags().shortValue());
66         outBuffer.writeInt(action.getNxActionConntrack().getZoneSrc().intValue());
67         outBuffer.writeShort(action.getNxActionConntrack().getConntrackZone().shortValue());
68         outBuffer.writeByte(action.getNxActionConntrack().getRecircTable().byteValue());
69         outBuffer.writeZero(5);
70         serializeCtAction(outBuffer,action, length);
71     }
72
73     private int getActionLength(final ActionConntrack action) {
74         int length = 0;
75         List<CtActions> ctActionsList = action.getNxActionConntrack().getCtActions();
76         if (ctActionsList == null) {
77             return length;
78         }
79         for (CtActions ctActions : ctActionsList) {
80             if (ctActions.getOfpactActions() instanceof NxActionNatCase) {
81                 length += NX_NAT_LENGTH;
82                 NxActionNatCase nxActionNatCase = (NxActionNatCase)ctActions.getOfpactActions();
83                 NxActionNat natAction = nxActionNatCase.getNxActionNat();
84                 short rangePresent = natAction.getRangePresent().shortValue();
85                 if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MIN.getIntValue())) {
86                     length += INT_LENGTH;
87                 }
88                 if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MAX.getIntValue())) {
89                     length += INT_LENGTH;
90                 }
91                 if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMIN.getIntValue())) {
92                     length += SHORT_LENGTH;
93                 }
94                 if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMAX.getIntValue())) {
95                     length += SHORT_LENGTH;
96                 }
97             }
98         }
99         LOG.trace("ActionLength :conntrack: length {}",length);
100         return length;
101     }
102
103     private void serializeCtAction(final ByteBuf outBuffer, final ActionConntrack action, final int length) {
104         List<CtActions> ctActionsList = action.getNxActionConntrack().getCtActions();
105         if (ctActionsList != null) {
106             for (CtActions ctActions : ctActionsList) {
107                 if (ctActions.getOfpactActions() instanceof NxActionNatCase){
108                     NxActionNatCase nxActionNatCase = (NxActionNatCase)ctActions.getOfpactActions();
109                     NxActionNat natAction = nxActionNatCase.getNxActionNat();
110                     int pad = length % 8;
111                     serializeHeader(length + pad, NXAST_NAT_SUBTYPE, outBuffer);
112                     outBuffer.writeZero(2);
113                     outBuffer.writeShort(natAction.getFlags().shortValue());
114                     short rangePresent = natAction.getRangePresent().shortValue();
115                     outBuffer.writeShort(rangePresent);
116                     if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MIN.getIntValue())) {
117                         if (null != natAction.getIpAddressMin()) {
118                             outBuffer.writeBytes(IetfInetUtil.INSTANCE.ipv4AddressBytes(natAction
119                                     .getIpAddressMin().getIpv4Address()));
120                         }
121                     }
122                     if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MAX.getIntValue())) {
123                         if (null != natAction.getIpAddressMax()) {
124                             outBuffer.writeBytes(IetfInetUtil.INSTANCE.ipv4AddressBytes(natAction
125                                     .getIpAddressMax().getIpv4Address()));
126                         }
127                     }
128                     if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMIN.getIntValue())) {
129                         outBuffer.writeShort(natAction.getPortMin());
130                     }
131                     if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMAX.getIntValue())) {
132                         outBuffer.writeShort(natAction.getPortMax());
133                     }
134                     outBuffer.writeZero(pad);
135                 }
136             }
137         }
138     }
139
140     @Override
141     public Action deserialize(final ByteBuf message) {
142         short length = deserializeCtHeader(message);
143         NxActionConntrackBuilder nxActionConntrackBuilder = new NxActionConntrackBuilder();
144         nxActionConntrackBuilder.setFlags(message.readUnsignedShort());
145         nxActionConntrackBuilder.setZoneSrc(message.readUnsignedInt());
146         nxActionConntrackBuilder.setConntrackZone(message.readUnsignedShort());
147         nxActionConntrackBuilder.setRecircTable(message.readUnsignedByte());
148         message.skipBytes(5);
149         if  (length > CT_LENGTH) {
150             dserializeCtAction(message,nxActionConntrackBuilder);
151         }
152         ActionBuilder actionBuilder = new ActionBuilder();
153         actionBuilder.setExperimenterId(getExperimenterId());
154         ActionConntrackBuilder actionConntrackBuilder = new ActionConntrackBuilder();
155         actionConntrackBuilder.setNxActionConntrack(nxActionConntrackBuilder.build());
156         actionBuilder.setActionChoice(actionConntrackBuilder.build());
157         return actionBuilder.build();
158     }
159
160     private void dserializeCtAction(final ByteBuf message, final NxActionConntrackBuilder nxActionConntrackBuilder) {
161         deserializeCtHeader(message);
162
163         NxActionNatBuilder nxActionNatBuilder = new NxActionNatBuilder();
164         message.skipBytes(2);
165         nxActionNatBuilder.setFlags(message.readUnsignedShort());
166
167         int rangePresent = message.readUnsignedShort();
168         nxActionNatBuilder.setRangePresent(rangePresent);
169         if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MIN.getIntValue())) {
170             InetAddress address = InetAddresses.fromInteger((int)message.readUnsignedInt());
171             nxActionNatBuilder.setIpAddressMin(new IpAddress(address.getHostAddress().toCharArray()));
172         }
173         if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MAX.getIntValue())) {
174             InetAddress address = InetAddresses.fromInteger((int)message.readUnsignedInt());
175             nxActionNatBuilder.setIpAddressMax(new IpAddress(address.getHostAddress().toCharArray()));
176         }
177         if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMIN.getIntValue())) {
178             nxActionNatBuilder.setPortMin(message.readUnsignedShort());
179         }
180         if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMAX.getIntValue())) {
181             nxActionNatBuilder.setPortMax(message.readUnsignedShort());
182         }
183         NxActionNatCaseBuilder caseBuilder = new NxActionNatCaseBuilder();
184         caseBuilder.setNxActionNat(nxActionNatBuilder.build());
185         CtActionsBuilder ctActionsBuilder = new CtActionsBuilder();
186         ctActionsBuilder.setOfpactActions(caseBuilder.build());
187         List<CtActions> ctActionsList = new ArrayList<>();
188         ctActionsList.add(ctActionsBuilder.build());
189         nxActionConntrackBuilder.setCtActions(ctActionsList);
190     }
191
192     private short deserializeCtHeader(final ByteBuf message) {
193         // size of experimenter type
194         message.skipBytes(EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
195         // size of length
196         short length = message.readShort();
197         // vendor id
198         message.skipBytes(EncodeConstants.SIZE_OF_INT_IN_BYTES);
199         // subtype
200         message.skipBytes(EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
201         return length;
202     }
203
204
205
206 }