/* * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.openflowplugin.impl.device; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InOrder; import org.mockito.Matchers; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.runners.MockitoJUnitRunner; import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter; import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext; import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy; /** * Test for {@link PacketInRateLimiter}. */ @RunWith(MockitoJUnitRunner.class) public class PacketInRateLimiterTest { private PacketInRateLimiter rateLimiter; @Mock private ConnectionAdapter connectionAdapter; @Mock private MessageSpy messageSpy; private InOrder caOrdered; @Before public void setUp() throws Exception { caOrdered = Mockito.inOrder(connectionAdapter); rateLimiter = new PacketInRateLimiter(connectionAdapter, 4, 10, messageSpy, 0.5f); } @Test public void testDisableFlow() throws Exception { rateLimiter.disableFlow(); Mockito.verify(messageSpy).spyMessage(DeviceContext.class, MessageSpy.STATISTIC_GROUP.OFJ_BACKPRESSURE_ON); Mockito.verify(connectionAdapter).setPacketInFiltering(true); } @Test public void testEnableFlow() throws Exception { rateLimiter.enableFlow(); Mockito.verify(messageSpy).spyMessage(DeviceContext.class, MessageSpy.STATISTIC_GROUP.OFJ_BACKPRESSURE_OFF); Mockito.verify(connectionAdapter).setPacketInFiltering(false); } @Test public void testDrainLowWaterMark() throws Exception { // scenario: // occupy 4 permits // drain low water mark = lwm temporarily set to 50% (= 2) and get limited // need to free 2 permits to escape the limit and reset lwm // now free to get more than 2 permits Assert.assertEquals(0, rateLimiter.getOccupiedPermits()); Assert.assertFalse(rateLimiter.isLimited()); acquirePermits(4); Assert.assertEquals(4, rateLimiter.getOccupiedPermits()); // drain current rateLimiter.drainLowWaterMark(); Assert.assertEquals(4, rateLimiter.getOccupiedPermits()); Assert.assertTrue(rateLimiter.isLimited()); caOrdered.verify(connectionAdapter).setPacketInFiltering(true); // release 1 permit -> 3 occupied but threshold = 2 -> stay limited rateLimiter.releasePermit(); Assert.assertEquals(3, rateLimiter.getOccupiedPermits()); Assert.assertTrue(rateLimiter.isLimited()); // release 1 permit -> 2 occupied but threshold = 2 -> escape limit rateLimiter.releasePermit(); Assert.assertEquals(2, rateLimiter.getOccupiedPermits()); Assert.assertFalse(rateLimiter.isLimited()); caOrdered.verify(connectionAdapter).setPacketInFiltering(false); // lwm is reset acquirePermits(4); Assert.assertEquals(6, rateLimiter.getOccupiedPermits()); Assert.assertFalse(rateLimiter.isLimited()); Mockito.verify(connectionAdapter, Mockito.times(2)).setPacketInFiltering(Matchers.anyBoolean()); } private void acquirePermits(int permits) { for (int i = 0; i < permits; i++) { final boolean gainedPermit = rateLimiter.acquirePermit(); if (!gainedPermit) { throw new IllegalStateException("not enough permits"); } } } private void releasePermits(int permits) { for (int i = 0; i < permits; i++) { rateLimiter.releasePermit(); } } @Test public void testAcquirePermit() throws Exception { Assert.assertEquals(0, rateLimiter.getOccupiedPermits()); Assert.assertFalse(rateLimiter.isLimited()); // approach hwm acquirePermits(10); Assert.assertEquals(10, rateLimiter.getOccupiedPermits()); Assert.assertFalse(rateLimiter.isLimited()); // hit hwm Assert.assertFalse(rateLimiter.acquirePermit()); Assert.assertEquals(10, rateLimiter.getOccupiedPermits()); Assert.assertTrue(rateLimiter.isLimited()); caOrdered.verify(connectionAdapter).setPacketInFiltering(true); // approach lwm releasePermits(5); Assert.assertEquals(5, rateLimiter.getOccupiedPermits()); Assert.assertTrue(rateLimiter.isLimited()); // cross lwm rateLimiter.releasePermit(); Assert.assertEquals(4, rateLimiter.getOccupiedPermits()); Assert.assertFalse(rateLimiter.isLimited()); caOrdered.verify(connectionAdapter).setPacketInFiltering(false); Mockito.verify(connectionAdapter, Mockito.times(2)).setPacketInFiltering(Matchers.anyBoolean()); } @Test public void testChangeWaterMarks1() throws Exception { rateLimiter.changeWaterMarks(2, 4); acquirePermits(4); Assert.assertEquals(4, rateLimiter.getOccupiedPermits()); Assert.assertFalse(rateLimiter.isLimited()); // hit hwm Assert.assertFalse(rateLimiter.acquirePermit()); Assert.assertEquals(4, rateLimiter.getOccupiedPermits()); Assert.assertTrue(rateLimiter.isLimited()); caOrdered.verify(connectionAdapter).setPacketInFiltering(true); // approach lwm rateLimiter.releasePermit(); Assert.assertEquals(3, rateLimiter.getOccupiedPermits()); Assert.assertTrue(rateLimiter.isLimited()); // cross lwm, escape limit rateLimiter.releasePermit(); Assert.assertEquals(2, rateLimiter.getOccupiedPermits()); Assert.assertFalse(rateLimiter.isLimited()); caOrdered.verify(connectionAdapter).setPacketInFiltering(false); Mockito.verify(connectionAdapter, Mockito.times(2)).setPacketInFiltering(Matchers.anyBoolean()); } @Test public void testChangeWaterMarks2() throws Exception { // draining to lwm/occupied = 3/6 acquirePermits(6); rateLimiter.drainLowWaterMark(); Assert.assertEquals(6, rateLimiter.getOccupiedPermits()); Assert.assertTrue(rateLimiter.isLimited()); caOrdered.verify(connectionAdapter).setPacketInFiltering(true); rateLimiter.changeWaterMarks(7, 12); Assert.assertEquals(6, rateLimiter.getOccupiedPermits()); Assert.assertTrue(rateLimiter.isLimited()); // new lwm is equal to current occupied permits - we can acquire more but flow is still limited acquirePermits(1); Assert.assertTrue(rateLimiter.isLimited()); Assert.assertEquals(7, rateLimiter.getOccupiedPermits()); // cross lwm, escape old lwm limit, reset lwm rateLimiter.releasePermit(); Assert.assertEquals(6, rateLimiter.getOccupiedPermits()); Assert.assertFalse(rateLimiter.isLimited()); caOrdered.verify(connectionAdapter).setPacketInFiltering(false); // free to reach hwm of 12 acquirePermits(6); Assert.assertEquals(12, rateLimiter.getOccupiedPermits()); Assert.assertFalse(rateLimiter.isLimited()); Mockito.verify(connectionAdapter, Mockito.times(2)).setPacketInFiltering(Matchers.anyBoolean()); } }