Bug 6554 Fix rejecting connections
[openflowplugin.git] / openflowplugin-impl / src / test / java / org / opendaylight / openflowplugin / impl / device / PacketInRateLimiterTest.java
1 /*
2  * Copyright (c) 2015 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
9 package org.opendaylight.openflowplugin.impl.device;
10
11 import org.junit.Assert;
12 import org.junit.Before;
13 import org.junit.Test;
14 import org.junit.runner.RunWith;
15 import org.mockito.InOrder;
16 import org.mockito.Matchers;
17 import org.mockito.Mock;
18 import org.mockito.Mockito;
19 import org.mockito.runners.MockitoJUnitRunner;
20 import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
21 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
22 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
23
24 /**
25  * Test for {@link PacketInRateLimiter}.
26  */
27 @RunWith(MockitoJUnitRunner.class)
28 public class PacketInRateLimiterTest {
29
30     private PacketInRateLimiter rateLimiter;
31     @Mock
32     private ConnectionAdapter connectionAdapter;
33     @Mock
34     private MessageSpy messageSpy;
35     private InOrder caOrdered;
36
37     @Before
38     public void setUp() throws Exception {
39         caOrdered = Mockito.inOrder(connectionAdapter);
40         rateLimiter = new PacketInRateLimiter(connectionAdapter, 4, 10, messageSpy, 0.5f);
41     }
42
43     @Test
44     public void testDisableFlow() throws Exception {
45         rateLimiter.disableFlow();
46
47         Mockito.verify(messageSpy).spyMessage(DeviceContext.class, MessageSpy.STATISTIC_GROUP.OFJ_BACKPRESSURE_ON);
48         Mockito.verify(connectionAdapter).setPacketInFiltering(true);
49     }
50
51     @Test
52     public void testEnableFlow() throws Exception {
53         rateLimiter.enableFlow();
54
55         Mockito.verify(messageSpy).spyMessage(DeviceContext.class, MessageSpy.STATISTIC_GROUP.OFJ_BACKPRESSURE_OFF);
56         Mockito.verify(connectionAdapter).setPacketInFiltering(false);
57     }
58
59     @Test
60     public void testDrainLowWaterMark() throws Exception {
61         // scenario:
62         // occupy 4 permits
63         // drain low water mark = lwm temporarily set to 50% (= 2) and get limited
64         // need to free 2 permits to escape the limit and reset lwm
65         // now free to get more than 2 permits
66
67         Assert.assertEquals(0, rateLimiter.getOccupiedPermits());
68         Assert.assertFalse(rateLimiter.isLimited());
69         acquirePermits(4);
70         Assert.assertEquals(4, rateLimiter.getOccupiedPermits());
71
72         // drain current
73         rateLimiter.drainLowWaterMark();
74         Assert.assertEquals(4, rateLimiter.getOccupiedPermits());
75         Assert.assertTrue(rateLimiter.isLimited());
76         caOrdered.verify(connectionAdapter).setPacketInFiltering(true);
77
78         // release 1 permit ->  3 occupied but threshold = 2 -> stay limited
79         rateLimiter.releasePermit();
80         Assert.assertEquals(3, rateLimiter.getOccupiedPermits());
81         Assert.assertTrue(rateLimiter.isLimited());
82
83         // release 1 permit ->  2 occupied but threshold = 2 -> escape limit
84         rateLimiter.releasePermit();
85         Assert.assertEquals(2, rateLimiter.getOccupiedPermits());
86         Assert.assertFalse(rateLimiter.isLimited());
87         caOrdered.verify(connectionAdapter).setPacketInFiltering(false);
88
89         // lwm is reset
90         acquirePermits(4);
91         Assert.assertEquals(6, rateLimiter.getOccupiedPermits());
92         Assert.assertFalse(rateLimiter.isLimited());
93
94         Mockito.verify(connectionAdapter, Mockito.times(2)).setPacketInFiltering(Matchers.anyBoolean());
95     }
96
97     private void acquirePermits(int permits) {
98         for (int i = 0; i < permits; i++) {
99             final boolean gainedPermit = rateLimiter.acquirePermit();
100             if (!gainedPermit) {
101                 throw new IllegalStateException("not enough permits");
102             }
103         }
104     }
105
106     private void releasePermits(int permits) {
107         for (int i = 0; i < permits; i++) {
108             rateLimiter.releasePermit();
109         }
110     }
111
112     @Test
113     public void testAcquirePermit() throws Exception {
114         Assert.assertEquals(0, rateLimiter.getOccupiedPermits());
115         Assert.assertFalse(rateLimiter.isLimited());
116
117         // approach hwm
118         acquirePermits(10);
119         Assert.assertEquals(10, rateLimiter.getOccupiedPermits());
120         Assert.assertFalse(rateLimiter.isLimited());
121
122         // hit hwm
123         Assert.assertFalse(rateLimiter.acquirePermit());
124         Assert.assertEquals(10, rateLimiter.getOccupiedPermits());
125         Assert.assertTrue(rateLimiter.isLimited());
126         caOrdered.verify(connectionAdapter).setPacketInFiltering(true);
127
128         // approach lwm
129         releasePermits(5);
130         Assert.assertEquals(5, rateLimiter.getOccupiedPermits());
131         Assert.assertTrue(rateLimiter.isLimited());
132
133         // cross lwm
134         rateLimiter.releasePermit();
135         Assert.assertEquals(4, rateLimiter.getOccupiedPermits());
136         Assert.assertFalse(rateLimiter.isLimited());
137         caOrdered.verify(connectionAdapter).setPacketInFiltering(false);
138
139         Mockito.verify(connectionAdapter, Mockito.times(2)).setPacketInFiltering(Matchers.anyBoolean());
140     }
141
142     @Test
143     public void testChangeWaterMarks1() throws Exception {
144         rateLimiter.changeWaterMarks(2, 4);
145         acquirePermits(4);
146         Assert.assertEquals(4, rateLimiter.getOccupiedPermits());
147         Assert.assertFalse(rateLimiter.isLimited());
148
149         // hit hwm
150         Assert.assertFalse(rateLimiter.acquirePermit());
151         Assert.assertEquals(4, rateLimiter.getOccupiedPermits());
152         Assert.assertTrue(rateLimiter.isLimited());
153         caOrdered.verify(connectionAdapter).setPacketInFiltering(true);
154
155         // approach lwm
156         rateLimiter.releasePermit();
157         Assert.assertEquals(3, rateLimiter.getOccupiedPermits());
158         Assert.assertTrue(rateLimiter.isLimited());
159
160         // cross lwm, escape limit
161         rateLimiter.releasePermit();
162         Assert.assertEquals(2, rateLimiter.getOccupiedPermits());
163         Assert.assertFalse(rateLimiter.isLimited());
164         caOrdered.verify(connectionAdapter).setPacketInFiltering(false);
165
166         Mockito.verify(connectionAdapter, Mockito.times(2)).setPacketInFiltering(Matchers.anyBoolean());
167     }
168
169     @Test
170     public void testChangeWaterMarks2() throws Exception {
171         // draining to lwm/occupied = 3/6
172         acquirePermits(6);
173         rateLimiter.drainLowWaterMark();
174         Assert.assertEquals(6, rateLimiter.getOccupiedPermits());
175         Assert.assertTrue(rateLimiter.isLimited());
176         caOrdered.verify(connectionAdapter).setPacketInFiltering(true);
177
178         rateLimiter.changeWaterMarks(7, 12);
179         Assert.assertEquals(6, rateLimiter.getOccupiedPermits());
180         Assert.assertTrue(rateLimiter.isLimited());
181
182         // new lwm is equal to current occupied permits - we can acquire more but flow is still limited
183         acquirePermits(1);
184         Assert.assertTrue(rateLimiter.isLimited());
185         Assert.assertEquals(7, rateLimiter.getOccupiedPermits());
186
187         // cross lwm, escape old lwm limit, reset lwm
188         rateLimiter.releasePermit();
189         Assert.assertEquals(6, rateLimiter.getOccupiedPermits());
190         Assert.assertFalse(rateLimiter.isLimited());
191         caOrdered.verify(connectionAdapter).setPacketInFiltering(false);
192
193         // free to reach hwm of 12
194         acquirePermits(6);
195         Assert.assertEquals(12, rateLimiter.getOccupiedPermits());
196         Assert.assertFalse(rateLimiter.isLimited());
197
198         Mockito.verify(connectionAdapter, Mockito.times(2)).setPacketInFiltering(Matchers.anyBoolean());
199     }
200 }