13c16051808fa62bc6d6675164da6fc8aaa77e06
[openflowplugin.git] / openflowplugin / src / test / java / org / opendaylight / openflowplugin / openflow / md / core / sal / convertor / match / MatchConvertorImplTest.java
1 /*
2  * Copyright (c) 2014 NEC Corporation 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.openflowplugin.openflow.md.core.sal.convertor.match;
10
11 import static org.junit.Assert.assertEquals;
12
13 import java.math.BigInteger;
14 import java.util.ArrayList;
15 import java.util.List;
16
17 import org.junit.BeforeClass;
18 import org.junit.Test;
19
20 import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
21 import org.opendaylight.openflowplugin.openflow.md.util.OpenflowPortsUtil;
22
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatch;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatch;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.EthTypeMatchEntry;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.EthTypeMatchEntryBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MaskMatchEntry;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MaskMatchEntryBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.PortNumberMatchEntry;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.PortNumberMatchEntryBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.VlanVidMatchEntry;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.VlanVidMatchEntryBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.EtherType;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowWildcardsV10;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortNumber;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.EthDst;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.EthSrc;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.EthType;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.InPort;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.MatchField;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.OpenflowBasicClass;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.OxmMatchType;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.VlanVid;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.match.v10.grouping.MatchV10;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.match.v10.grouping.MatchV10Builder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.oxm.fields.grouping.MatchEntries;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.oxm.fields.grouping.MatchEntriesBuilder;
55
56 /**
57  * Unit test for {@link MatchConvertorImpl}.
58  */
59 public class MatchConvertorImplTest {
60     private static final BigInteger  DPID = BigInteger.TEN;
61     private static final Long  IN_PORT = Long.valueOf(6);
62     private static final String  URI_IN_PORT =
63         "openflow:" + DPID + ":" + IN_PORT;
64     private static final MacAddress MAC_SRC =
65         MacAddress.getDefaultInstance("00:11:22:33:44:55");
66     private static final MacAddress MAC_DST =
67         MacAddress.getDefaultInstance("fa:fb:fc:fd:fe:ff");
68     private static final int  ETHTYPE_IPV4 = 0x800;
69     private static final short  VLAN_PCP = 7;
70     private static final Ipv4Address  IPV4_SRC =
71         Ipv4Address.getDefaultInstance("192.168.10.254");
72     private static final Ipv4Address  IPV4_DST =
73         Ipv4Address.getDefaultInstance("10.1.2.3");
74
75     private static final int  DL_VLAN_NONE = 0xffff;
76
77     @BeforeClass
78     public static void setUp() {
79         OpenflowPortsUtil.init();
80     }
81
82     /**
83      * Test method for {@link MatchConvertorImpl#fromOFMatchToSALMatch(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.match.grouping.Match, BigInteger, OpenflowVersion)}.
84      */
85     @Test
86     public void testFromOFMatchToSALMatch() {
87         List<MatchEntries> entries = createDefaultMatchEntries();
88
89         int[] vids = {
90             // Match packet with VLAN tag regardless of its value.
91             -1,
92
93             // Match untagged frame.
94             0,
95
96             // Match packet with VLAN tag and VID equals the specified value.
97             1, 20, 4095,
98         };
99
100         for (int vid: vids) {
101             List<MatchEntries> matchEntries =
102                 new ArrayList<MatchEntries>(entries);
103             matchEntries.add(toOfVlanVid(vid));
104             org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.match.grouping.Match ofMatch =
105                 createOFMatch(matchEntries);
106
107             MatchBuilder builder = MatchConvertorImpl.
108                 fromOFMatchToSALMatch(ofMatch, DPID, OpenflowVersion.OF13);
109             checkDefault(builder);
110             VlanMatch vlanMatch = builder.getVlanMatch();
111             int expectedVid = (vid < 0) ? 0 : vid;
112             Boolean expectedCfi = Boolean.valueOf(vid != 0);
113             assertEquals(expectedVid, vlanMatch.getVlanId().getVlanId().
114                          getValue().intValue());
115             assertEquals(expectedCfi, vlanMatch.getVlanId().isVlanIdPresent());
116             assertEquals(null, vlanMatch.getVlanPcp());
117         }
118     }
119
120     /**
121      * Test method for {@link MatchConvertorImpl#fromOFMatchV10ToSALMatch(MatchV10, BigInteger, OpenflowVersion)}.
122      */
123     @Test
124     public void testFromOFMatchV10ToSALMatch() {
125         int[] vids = {
126             // Match untagged frame.
127             DL_VLAN_NONE,
128
129             // Match packet with VLAN tag and VID equals the specified value.
130             1, 20, 4095,
131         };
132         short[] dscps = {
133             0, 1, 20, 40, 62, 63,
134         };
135
136         FlowWildcardsV10Builder wcBuilder = new FlowWildcardsV10Builder();
137         for (int vid: vids) {
138             for (short dscp: dscps) {
139                 short tos = (short)(dscp << 2);
140                 MatchV10Builder builder = new MatchV10Builder();
141                 builder.setDlSrc(MAC_SRC).setDlDst(MAC_DST).setDlVlan(vid).
142                     setDlVlanPcp(VLAN_PCP).setDlType(ETHTYPE_IPV4).
143                     setInPort(IN_PORT.intValue()).
144                     setNwSrc(IPV4_SRC).setNwDst(IPV4_DST).setNwTos(tos);
145                 wcBuilder.setAll(false).setNwProto(true).setTpSrc(true).
146                     setTpDst(true);
147                 if (vid == DL_VLAN_NONE) {
148                     wcBuilder.setDlVlanPcp(true);
149                 }
150
151                 FlowWildcardsV10 wc = wcBuilder.build();
152                 MatchV10 ofMatch = builder.setWildcards(wc).build();
153                 Match match = MatchConvertorImpl.fromOFMatchV10ToSALMatch(
154                     ofMatch, DPID, OpenflowVersion.OF10);
155                 checkDefaultV10(match, wc, vid);
156
157                 IpMatch ipMatch = match.getIpMatch();
158                 assertEquals(null, ipMatch.getIpProtocol());
159                 assertEquals(dscp, ipMatch.getIpDscp().getValue().shortValue());
160                 assertEquals(null, ipMatch.getIpEcn());
161
162                 // Set all wildcard bits.
163                 wc = wcBuilder.setAll(true).build();
164                 ofMatch = builder.setWildcards(wc).build();
165                 match = MatchConvertorImpl.fromOFMatchV10ToSALMatch(
166                     ofMatch, DPID, OpenflowVersion.OF10);
167                 checkDefaultV10(match, wc, vid);
168                 assertEquals(null, match.getIpMatch());
169             }
170         }
171     }
172
173     private void checkDefault(MatchBuilder builder) {
174         EthernetMatch ethMatch = builder.getEthernetMatch();
175         assertEquals(MAC_SRC, ethMatch.getEthernetSource().getAddress());
176         assertEquals(null, ethMatch.getEthernetSource().getMask());
177         assertEquals(MAC_DST, ethMatch.getEthernetDestination().getAddress());
178         assertEquals(null, ethMatch.getEthernetDestination().getMask());
179         assertEquals(ETHTYPE_IPV4, ethMatch.getEthernetType().getType().
180                      getValue().intValue());
181
182         NodeConnectorId inPort = builder.getInPort();
183         assertEquals(URI_IN_PORT, inPort.getValue());
184     }
185
186     private org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.match.grouping.Match createOFMatch(List<MatchEntries> entries) {
187         org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.match.grouping.MatchBuilder builder =
188             new org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.match.grouping.MatchBuilder();
189         return builder.setType(OxmMatchType.class).setMatchEntries(entries).
190             build();
191     }
192
193     private List<MatchEntries> createDefaultMatchEntries() {
194         List<MatchEntries> entries = new ArrayList<MatchEntries>();
195         entries.add(toOfPort(InPort.class, IN_PORT));
196         entries.add(MatchConvertorImpl.toOfMacAddress(
197                         EthSrc.class, MAC_SRC, null));
198         entries.add(MatchConvertorImpl.toOfMacAddress(
199                         EthDst.class, MAC_DST, null));
200         entries.add(toOfEthernetType(ETHTYPE_IPV4));
201         return entries;
202     }
203
204     private MatchEntries toOfEthernetType(int ethType) {
205         MatchEntriesBuilder builder = new MatchEntriesBuilder();
206         builder.setOxmClass(OpenflowBasicClass.class);
207         builder.setHasMask(false);
208         builder.setOxmMatchField(EthType.class);
209         EthTypeMatchEntryBuilder ethTypeBuilder =
210             new EthTypeMatchEntryBuilder();
211         ethTypeBuilder.setEthType(new EtherType(ethType));
212         builder.addAugmentation(EthTypeMatchEntry.class,
213                                 ethTypeBuilder.build());
214         return builder.build();
215     }
216
217     private MatchEntries toOfPort(Class<? extends MatchField> field,
218                                   Long portNumber) {
219         MatchEntriesBuilder builder = new MatchEntriesBuilder();
220         builder.setOxmClass(OpenflowBasicClass.class);
221         builder.setHasMask(false);
222         builder.setOxmMatchField(field);
223         PortNumberMatchEntryBuilder portBuilder =
224             new PortNumberMatchEntryBuilder();
225         portBuilder.setPortNumber(new PortNumber(portNumber));
226         builder.addAugmentation(PortNumberMatchEntry.class,
227                                             portBuilder.build());
228         return builder.build();
229     }
230
231     private MatchEntries toOfVlanVid(int vid) {
232         MatchEntriesBuilder builder = new MatchEntriesBuilder();
233         boolean cfi = true;
234         Integer vidValue = Integer.valueOf(vid);
235         byte[] mask = null;
236         builder.setOxmClass(OpenflowBasicClass.class);
237         builder.setOxmMatchField(VlanVid.class);
238         VlanVidMatchEntryBuilder vidBuilder = new VlanVidMatchEntryBuilder();
239         if (vid == 0) {
240             // Match untagged frame.
241             cfi = false;
242         } else if (vid < 0) {
243             // Match packet with VLAN tag regardless of its value.
244             mask = new byte[]{0x10, 0x00};
245             vidValue = Integer.valueOf(0);
246         }
247
248         vidBuilder.setCfiBit(cfi);
249         vidBuilder.setVlanVid(vidValue);
250         builder.addAugmentation(VlanVidMatchEntry.class, vidBuilder.build());
251         boolean hasMask = mask != null;
252         if (hasMask) {
253             addMaskAugmentation(builder, mask);
254         }
255         builder.setHasMask(hasMask);
256         return builder.build();
257     }
258
259     private void addMaskAugmentation(MatchEntriesBuilder builder, byte[] mask) {
260         MaskMatchEntryBuilder maskBuilder = new MaskMatchEntryBuilder();
261         maskBuilder.setMask(mask);
262         builder.addAugmentation(MaskMatchEntry.class, maskBuilder.build());
263     }
264
265     private void checkDefaultV10(Match match, FlowWildcardsV10 wc, int vid) {
266         EthernetMatch ethMatch = match.getEthernetMatch();
267         if (wc.isDLSRC().booleanValue()) {
268             if (ethMatch != null) {
269                 assertEquals(null, ethMatch.getEthernetSource());
270             }
271         } else {
272             assertEquals(MAC_SRC, ethMatch.getEthernetSource().getAddress());
273         }
274
275         if (wc.isDLDST().booleanValue()) {
276             if (ethMatch != null) {
277                 assertEquals(null, ethMatch.getEthernetDestination());
278             }
279         } else {
280             assertEquals(MAC_DST,
281                          ethMatch.getEthernetDestination().getAddress());
282         }
283
284         if (wc.isDLTYPE().booleanValue()) {
285             if (ethMatch != null) {
286                 assertEquals(null, ethMatch.getEthernetType());
287             }
288             assertEquals(null, match.getLayer3Match());
289         } else {
290             assertEquals(ETHTYPE_IPV4, ethMatch.getEthernetType().getType().
291                          getValue().intValue());
292
293             Ipv4Match ipv4Match = (Ipv4Match)match.getLayer3Match();
294             assertEquals(IPV4_SRC.getValue()+"/32",
295                          ipv4Match.getIpv4Source().getValue());
296             assertEquals(IPV4_DST.getValue()+"/32",
297                          ipv4Match.getIpv4Destination().getValue());
298         }
299
300         VlanMatch vlanMatch = match.getVlanMatch();
301         if (wc.isDLVLAN().booleanValue()) {
302             assertEquals(null, vlanMatch);
303         } else {
304             int expectedVid;
305             Boolean expectedCfi;
306             if (vid == DL_VLAN_NONE) {
307                 expectedVid = 0;
308                 expectedCfi = Boolean.FALSE;
309             } else {
310                 expectedVid = vid;
311                 expectedCfi = Boolean.TRUE;
312             }
313             assertEquals(expectedVid, vlanMatch.getVlanId().getVlanId().
314                          getValue().intValue());
315             assertEquals(expectedCfi, vlanMatch.getVlanId().isVlanIdPresent());
316
317             if (wc.isDLVLANPCP().booleanValue()) {
318                 assertEquals(null, vlanMatch.getVlanPcp());
319             } else {
320                 assertEquals(VLAN_PCP,
321                              vlanMatch.getVlanPcp().getValue().shortValue());
322             }
323         }
324     }
325 }