1 /* Copyright (C)2013 Pantheon Technologies, s.r.o. All rights reserved. */
\r
2 package org.opendaylight.openflowjava.protocol.impl.util;
\r
4 import io.netty.buffer.ByteBuf;
\r
6 import java.util.List;
\r
8 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.BosMatchEntry;
\r
9 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.EthTypeMatchEntry;
\r
10 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Icmpv4CodeMatchEntry;
\r
11 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Icmpv4TypeMatchEntry;
\r
12 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Icmpv6CodeMatchEntry;
\r
13 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Icmpv6TypeMatchEntry;
\r
14 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MacAddressMatchEntry;
\r
15 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MaskMatchEntry;
\r
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MetadataMatchEntry;
\r
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MplsLabelMatchEntry;
\r
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.OpCodeMatchEntry;
\r
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.PortMatchEntry;
\r
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.PortNumberMatchEntry;
\r
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.TcMatchEntry;
\r
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.VlanPcpMatchEntry;
\r
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.VlanVidMatchEntry;
\r
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.StandardMatchType;
\r
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.ArpOp;
\r
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.ArpSha;
\r
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.ArpSpa;
\r
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.ArpTha;
\r
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.ArpTpa;
\r
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Clazz;
\r
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.EthDst;
\r
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.EthSrc;
\r
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.EthType;
\r
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.ExperimenterClass;
\r
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Icmpv4Code;
\r
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Icmpv4Type;
\r
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Icmpv6Code;
\r
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Icmpv6Type;
\r
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.InPhyPort;
\r
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.InPort;
\r
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.IpDscp;
\r
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.IpEcn;
\r
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.IpProto;
\r
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Ipv4Dst;
\r
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Ipv4Src;
\r
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Ipv6Dst;
\r
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Ipv6Exthdr;
\r
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Ipv6Flabel;
\r
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Ipv6NdSll;
\r
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Ipv6NdTarget;
\r
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Ipv6NdTll;
\r
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Ipv6Src;
\r
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.MatchField;
\r
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Metadata;
\r
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.MplsBos;
\r
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.MplsLabel;
\r
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.MplsTc;
\r
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Nxm0Class;
\r
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Nxm1Class;
\r
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.OpenflowBasicClass;
\r
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.OxmMatchType;
\r
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.PbbIsid;
\r
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.SctpDst;
\r
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.SctpSrc;
\r
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.TcpDst;
\r
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.TcpSrc;
\r
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.TunnelId;
\r
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.UdpDst;
\r
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.UdpSrc;
\r
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.VlanPcp;
\r
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.VlanVid;
\r
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.oxm.fields.MatchEntries;
\r
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.flow.mod.Match;
\r
74 import org.slf4j.Logger;
\r
75 import org.slf4j.LoggerFactory;
\r
78 * @author michal.polkorab
\r
81 public class MatchSerializer {
\r
83 private static final Logger LOGGER = LoggerFactory.getLogger(MatchSerializer.class);
\r
87 * @param match ofp_match object
\r
88 * @param out output ByteBuf
\r
90 public static void encodeMatch(Match match, ByteBuf out) {
\r
91 final byte PADDING_IN_OFP_MATCH = 4;
\r
92 encodeType(match, out);
\r
93 //TODO - compute length
\r
94 encodeMatchEntries(match.getMatchEntries(), out);
\r
95 ByteBufUtils.padBuffer(PADDING_IN_OFP_MATCH, out);
\r
99 private static void encodeType(Match match, ByteBuf out) {
\r
100 final byte STANDARD_MATCH_TYPE_CODE = 0;
\r
101 final byte OXM_MATCH_TYPE_CODE = 1;
\r
102 if (match.getType().equals(StandardMatchType.class)) {
\r
103 out.writeShort(STANDARD_MATCH_TYPE_CODE);
\r
104 } else if (match.getType().equals(OxmMatchType.class)) {
\r
105 out.writeShort(OXM_MATCH_TYPE_CODE);
\r
109 private static void encodeMatchEntries(List<MatchEntries> matchEntries, ByteBuf out) {
\r
110 if (matchEntries == null) {
\r
111 LOGGER.warn("Match entry is null");
\r
114 for (MatchEntries entry : matchEntries) {
\r
115 encodeClass(entry.getOxmClass(), out);
\r
116 encodeRest(entry, null);
\r
120 private static void encodeClass(Class<? extends Clazz> clazz, ByteBuf out) {
\r
121 final int NXM0_CLASS_CODE = 0x0000;
\r
122 final int NXM1_CLASS_CODE = 0x0001;
\r
123 final int OPENFLOW_BASIC_CLASS_CODE = 0x8000;
\r
124 final int EXPERIMENTER_CLASS_CODE = 0xFFFF;
\r
125 if (Nxm0Class.class.equals(clazz)) {
\r
126 out.writeShort(NXM0_CLASS_CODE);
\r
127 } else if (Nxm1Class.class.equals(clazz)) {
\r
128 out.writeShort(NXM1_CLASS_CODE);
\r
129 } else if (OpenflowBasicClass.class.equals(clazz)) {
\r
130 out.writeShort(OPENFLOW_BASIC_CLASS_CODE);
\r
131 } else if (ExperimenterClass.class.equals(clazz)) {
\r
132 out.writeShort(EXPERIMENTER_CLASS_CODE);
\r
136 private static void encodeRest(MatchEntries entry, ByteBuf out) {
\r
137 int fieldValue = 0;
\r
138 Class<? extends MatchField> field = entry.getOxmMatchField();
\r
139 if (field.equals(InPort.class)) {
\r
141 writeOxmFieldAndLength(out, fieldValue, Integer.SIZE / Byte.SIZE);
\r
142 out.writeInt(entry.getAugmentation(PortNumberMatchEntry.class).getPortNumber().getValue().intValue());
\r
143 } else if (field.equals(InPhyPort.class)) {
\r
145 writeOxmFieldAndLength(out, fieldValue, Integer.SIZE / Byte.SIZE);
\r
146 out.writeInt(entry.getAugmentation(PortNumberMatchEntry.class).getPortNumber().getValue().intValue());
\r
147 } else if (field.equals(Metadata.class)) {
\r
149 fieldValue = fieldValue << 1;
\r
150 if (entry.isHasMask()) {
\r
151 fieldValue = fieldValue | 1;
\r
152 out.writeByte(fieldValue);
\r
153 byte[] mask = entry.getAugmentation(MaskMatchEntry.class).getMask();
\r
154 out.writeByte(Long.SIZE / Byte.SIZE + mask.length);
\r
155 out.writeBytes(entry.getAugmentation(MetadataMatchEntry.class).getMetadata());
\r
156 out.writeBytes(mask);
\r
158 out.writeByte(fieldValue);
\r
159 out.writeByte(Long.SIZE / Byte.SIZE);
\r
160 out.writeBytes(entry.getAugmentation(MetadataMatchEntry.class).getMetadata());
\r
162 } else if (field.equals(EthDst.class)) {
\r
164 fieldValue = fieldValue << 1;
\r
165 if (entry.isHasMask()) {
\r
166 fieldValue = fieldValue | 1;
\r
167 out.writeByte(fieldValue);
\r
168 byte[] mask = entry.getAugmentation(MaskMatchEntry.class).getMask();
\r
169 out.writeByte((Integer.SIZE + Short.SIZE) / Byte.SIZE + mask.length);
\r
170 out.writeBytes(entry.getAugmentation(MacAddressMatchEntry.class).getMacAddress().getValue().getBytes());
\r
171 out.writeBytes(entry.getAugmentation(MaskMatchEntry.class).getMask());
\r
173 out.writeByte(fieldValue);
\r
174 out.writeByte(Long.SIZE / Byte.SIZE);
\r
175 out.writeBytes(entry.getAugmentation(MacAddressMatchEntry.class).getMacAddress().getValue().getBytes());
\r
177 } else if (field.equals(EthSrc.class)) {
\r
179 fieldValue = fieldValue << 1;
\r
180 if (entry.isHasMask()) {
\r
181 fieldValue = fieldValue | 1;
\r
182 out.writeByte(fieldValue);
\r
183 byte[] mask = entry.getAugmentation(MaskMatchEntry.class).getMask();
\r
184 out.writeByte(Long.SIZE / Byte.SIZE + mask.length);
\r
185 out.writeBytes(entry.getAugmentation(MacAddressMatchEntry.class).getMacAddress().getValue().getBytes());
\r
186 out.writeBytes(mask);
\r
188 out.writeByte(fieldValue);
\r
189 out.writeByte(Long.SIZE / Byte.SIZE);
\r
190 out.writeBytes(entry.getAugmentation(MacAddressMatchEntry.class).getMacAddress().getValue().getBytes());
\r
192 } else if (field.equals(EthType.class)) {
\r
194 writeOxmFieldAndLength(out, fieldValue, Short.SIZE / Byte.SIZE);
\r
195 out.writeShort(entry.getAugmentation(EthTypeMatchEntry.class).getEthType().getValue().shortValue());
\r
196 } else if (field.equals(VlanVid.class)) {
\r
198 fieldValue = fieldValue << 1;
\r
199 if (entry.isHasMask()) {
\r
200 fieldValue = fieldValue | 1;
\r
201 out.writeByte(fieldValue);
\r
202 byte[] mask = entry.getAugmentation(MaskMatchEntry.class).getMask();
\r
203 out.writeByte(Short.SIZE / Byte.SIZE + mask.length);
\r
204 out.writeShort(entry.getAugmentation(VlanVidMatchEntry.class).getVlanVid());
\r
205 out.writeBytes(mask);
\r
207 writeOxmFieldAndLength(out, fieldValue, Short.SIZE / Byte.SIZE);
\r
208 out.writeShort(entry.getAugmentation(VlanVidMatchEntry.class).getVlanVid());
\r
210 } else if (field.equals(VlanPcp.class)) {
\r
212 writeOxmFieldAndLength(out, fieldValue, Byte.SIZE / Byte.SIZE);
\r
213 out.writeByte(entry.getAugmentation(VlanPcpMatchEntry.class).getVlanPcp().byteValue());
\r
214 } else if (field.equals(IpDscp.class)) {
\r
216 } else if (field.equals(IpEcn.class)) {
\r
218 } else if (field.equals(IpProto.class)) {
\r
220 } else if (field.equals(Ipv4Src.class)) {
\r
222 } else if (field.equals(Ipv4Dst.class)) {
\r
224 } else if (field.equals(TcpSrc.class)) {
\r
226 writeOxmFieldAndLength(out, fieldValue, Short.SIZE / Byte.SIZE);
\r
227 out.writeShort(entry.getAugmentation(PortMatchEntry.class).getPort().getValue().intValue());
\r
228 } else if (field.equals(TcpDst.class)) {
\r
230 writeOxmFieldAndLength(out, fieldValue, Short.SIZE / Byte.SIZE);
\r
231 out.writeShort(entry.getAugmentation(PortMatchEntry.class).getPort().getValue().intValue());
\r
232 } else if (field.equals(UdpSrc.class)) {
\r
234 writeOxmFieldAndLength(out, fieldValue, Short.SIZE / Byte.SIZE);
\r
235 out.writeShort(entry.getAugmentation(PortMatchEntry.class).getPort().getValue().intValue());
\r
236 } else if (field.equals(UdpDst.class)) {
\r
238 writeOxmFieldAndLength(out, fieldValue, Short.SIZE / Byte.SIZE);
\r
239 out.writeShort(entry.getAugmentation(PortMatchEntry.class).getPort().getValue().intValue());
\r
240 } else if (field.equals(SctpSrc.class)) {
\r
242 writeOxmFieldAndLength(out, fieldValue, Short.SIZE / Byte.SIZE);
\r
243 out.writeShort(entry.getAugmentation(PortMatchEntry.class).getPort().getValue().intValue());
\r
244 } else if (field.equals(SctpDst.class)) {
\r
246 writeOxmFieldAndLength(out, fieldValue, Short.SIZE / Byte.SIZE);
\r
247 out.writeShort(entry.getAugmentation(PortMatchEntry.class).getPort().getValue().intValue());
\r
248 } else if (field.equals(Icmpv4Type.class)) {
\r
250 writeOxmFieldAndLength(out, fieldValue, Byte.SIZE / Byte.SIZE);
\r
251 out.writeByte(entry.getAugmentation(Icmpv4TypeMatchEntry.class).getIcmpv4Type());
\r
252 } else if (field.equals(Icmpv4Code.class)) {
\r
254 writeOxmFieldAndLength(out, fieldValue, Byte.SIZE / Byte.SIZE);
\r
255 out.writeByte(entry.getAugmentation(Icmpv4CodeMatchEntry.class).getIcmpv4Code());
\r
256 } else if (field.equals(ArpOp.class)) {
\r
258 writeOxmFieldAndLength(out, fieldValue, Short.SIZE / Byte.SIZE);
\r
259 out.writeShort(entry.getAugmentation(OpCodeMatchEntry.class).getOpCode());
\r
260 } else if (field.equals(ArpSpa.class)) {
\r
262 } else if (field.equals(ArpTpa.class)) {
\r
264 } else if (field.equals(ArpSha.class)) {
\r
266 } else if (field.equals(ArpTha.class)) {
\r
268 } else if (field.equals(Ipv6Src.class)) {
\r
270 } else if (field.equals(Ipv6Dst.class)) {
\r
272 } else if (field.equals(Ipv6Flabel.class)) {
\r
274 } else if (field.equals(Icmpv6Type.class)) {
\r
276 writeOxmFieldAndLength(out, fieldValue, Byte.SIZE / Byte.SIZE);
\r
277 out.writeByte(entry.getAugmentation(Icmpv6TypeMatchEntry.class).getIcmpv6Type());
\r
278 } else if (field.equals(Icmpv6Code.class)) {
\r
280 writeOxmFieldAndLength(out, fieldValue, Byte.SIZE / Byte.SIZE);
\r
281 out.writeByte(entry.getAugmentation(Icmpv6CodeMatchEntry.class).getIcmpv6Code());
\r
282 } else if (field.equals(Ipv6NdTarget.class)) {
\r
284 } else if (field.equals(Ipv6NdSll.class)) {
\r
286 } else if (field.equals(Ipv6NdTll.class)) {
\r
288 } else if (field.equals(MplsLabel.class)) {
\r
290 writeOxmFieldAndLength(out, fieldValue, Integer.SIZE / Byte.SIZE);
\r
291 out.writeInt(entry.getAugmentation(MplsLabelMatchEntry.class).getMplsLabel().intValue());
\r
292 } else if (field.equals(MplsTc.class)) {
\r
294 writeOxmFieldAndLength(out, fieldValue, Byte.SIZE / Byte.SIZE);
\r
295 out.writeByte(entry.getAugmentation(TcMatchEntry.class).getTc());
\r
296 } else if (field.equals(MplsBos.class)) {
\r
298 writeOxmFieldAndLength(out, fieldValue, Byte.SIZE / Byte.SIZE);
\r
299 out.writeBoolean(entry.getAugmentation(BosMatchEntry.class).isBos().booleanValue());
\r
300 } else if (field.equals(PbbIsid.class)) {
\r
302 } else if (field.equals(TunnelId.class)) {
\r
304 } else if (field.equals(Ipv6Exthdr.class)) {
\r
309 private static void writeOxmFieldAndLength(ByteBuf out, int fieldValue, int length) {
\r
310 int fieldAndMask = fieldValue << 1;
\r
311 out.writeByte(fieldAndMask);
\r
312 out.writeByte(length);
\r