RouterTest.java 9.04 KB
/*
 * Copyright 2014 Open Networking Laboratory
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.onosproject.routing;

import com.google.common.collect.Sets;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultHost;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.HostLocation;
import org.onosproject.net.PortNumber;
import org.onosproject.net.host.HostListener;
import org.onosproject.net.host.HostService;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.routingapi.BgpService;
import org.onosproject.routingapi.FibEntry;
import org.onosproject.routingapi.FibListener;
import org.onosproject.routingapi.FibUpdate;
import org.onosproject.routingapi.RouteEntry;
import org.onosproject.routingapi.RouteListener;
import org.onosproject.routingapi.RouteUpdate;

import java.util.Collections;

import static org.easymock.EasyMock.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

/**
 * This class tests adding a route, updating a route, deleting a route,
 * and adding a route whose next hop is the local BGP speaker.
 * <p/>
 * The HostService answers requests synchronously.
 */
public class RouterTest {

    private HostService hostService;

    private FibListener fibListener;

    private static final ConnectPoint SW1_ETH1 = new ConnectPoint(
            DeviceId.deviceId("of:0000000000000001"),
            PortNumber.portNumber(1));

    private static final ConnectPoint SW2_ETH1 = new ConnectPoint(
            DeviceId.deviceId("of:0000000000000002"),
            PortNumber.portNumber(1));

    private static final ConnectPoint SW3_ETH1 = new ConnectPoint(
            DeviceId.deviceId("of:0000000000000003"),
            PortNumber.portNumber(1));

    private static final ConnectPoint SW4_ETH1 = new ConnectPoint(
            DeviceId.deviceId("of:0000000000000004"),
            PortNumber.portNumber(1));

    private Router router;

    @Before
    public void setUp() throws Exception {
        setUpHostService();

        BgpService bgpService = createMock(BgpService.class);
        bgpService.start(anyObject(RouteListener.class), anyInt());
        bgpService.stop();
        replay(bgpService);

        fibListener = createMock(FibListener.class);

        router = new Router();
        router.hostService = hostService;
        router.bgpService = bgpService;
        router.activate();

        router.start(fibListener);
    }

    @After
    public void tearDown() {
        router.stop();
    }

    /**
     * Sets up the host service with details of some hosts.
     */
    private void setUpHostService() {
        hostService = createMock(HostService.class);

        hostService.addListener(anyObject(HostListener.class));
        expectLastCall().anyTimes();

        IpAddress host1Address = IpAddress.valueOf("192.168.10.1");
        Host host1 = new DefaultHost(ProviderId.NONE, HostId.NONE,
                MacAddress.valueOf("00:00:00:00:00:01"), VlanId.NONE,
                new HostLocation(SW1_ETH1, 1),
                Sets.newHashSet(host1Address));

        expect(hostService.getHostsByIp(host1Address))
                .andReturn(Sets.newHashSet(host1)).anyTimes();
        hostService.startMonitoringIp(host1Address);
        expectLastCall().anyTimes();


        IpAddress host2Address = IpAddress.valueOf("192.168.20.1");
        Host host2 = new DefaultHost(ProviderId.NONE, HostId.NONE,
                MacAddress.valueOf("00:00:00:00:00:02"), VlanId.NONE,
                new HostLocation(SW2_ETH1, 1),
                Sets.newHashSet(host2Address));

        expect(hostService.getHostsByIp(host2Address))
                .andReturn(Sets.newHashSet(host2)).anyTimes();
        hostService.startMonitoringIp(host2Address);
        expectLastCall().anyTimes();

        // Next hop on a VLAN
        IpAddress host3Address = IpAddress.valueOf("192.168.40.1");
        Host host3 = new DefaultHost(ProviderId.NONE, HostId.NONE,
                MacAddress.valueOf("00:00:00:00:00:03"), VlanId.vlanId((short) 1),
                new HostLocation(SW4_ETH1, 1),
                Sets.newHashSet(host3Address));

        expect(hostService.getHostsByIp(host3Address))
                .andReturn(Sets.newHashSet(host3)).anyTimes();
        hostService.startMonitoringIp(host3Address);
        expectLastCall().anyTimes();

        // Called during shutdown
        hostService.removeListener(anyObject(HostListener.class));

        replay(hostService);
    }

    /**
     * Tests adding a route entry.
     */
    @Test
    public void testRouteAdd() {
        // Construct a route entry
        IpPrefix prefix = Ip4Prefix.valueOf("1.1.1.0/24");
        IpAddress nextHopIp = Ip4Address.valueOf("192.168.10.1");

        RouteEntry routeEntry = new RouteEntry(prefix, nextHopIp);

        // Expected FIB entry
        FibEntry fibEntry = new FibEntry(prefix, nextHopIp,
                                         MacAddress.valueOf("00:00:00:00:00:01"));

        fibListener.update(Collections.singletonList(new FibUpdate(
                FibUpdate.Type.UPDATE, fibEntry)), Collections.emptyList());

        replay(fibListener);

        router.processRouteUpdates(Collections.singletonList(
                new RouteUpdate(RouteUpdate.Type.UPDATE, routeEntry)));

        verify(fibListener);
    }

    /**
     * Tests updating a route entry.
     */
    @Test
    public void testRouteUpdate() {
        // Firstly add a route
        testRouteAdd();

        // Route entry with updated next hop for the original prefix
        RouteEntry routeEntryUpdate = new RouteEntry(
                Ip4Prefix.valueOf("1.1.1.0/24"),
                Ip4Address.valueOf("192.168.20.1"));

        // The old FIB entry will be withdrawn
        FibEntry withdrawFibEntry = new FibEntry(
                Ip4Prefix.valueOf("1.1.1.0/24"), null, null);

        // A new FIB entry will be added
        FibEntry updateFibEntry = new FibEntry(
                Ip4Prefix.valueOf("1.1.1.0/24"),
                Ip4Address.valueOf("192.168.20.1"),
                MacAddress.valueOf("00:00:00:00:00:02"));

        reset(fibListener);
        fibListener.update(Collections.singletonList(new FibUpdate(
                                    FibUpdate.Type.UPDATE, updateFibEntry)),
                           Collections.singletonList(new FibUpdate(
                                    FibUpdate.Type.DELETE, withdrawFibEntry)));

        replay(fibListener);

        router.processRouteUpdates(Collections.singletonList(new RouteUpdate(
                RouteUpdate.Type.UPDATE, routeEntryUpdate)));

        verify(fibListener);
    }

    /**
     * Tests deleting a route entry.
     */
    @Test
    public void testRouteDelete() {
        // Firstly add a route
        testRouteAdd();

        RouteEntry deleteRouteEntry = new RouteEntry(
                Ip4Prefix.valueOf("1.1.1.0/24"),
                Ip4Address.valueOf("192.168.10.1"));

        FibEntry deleteFibEntry = new FibEntry(
                Ip4Prefix.valueOf("1.1.1.0/24"), null, null);

        reset(fibListener);
        fibListener.update(Collections.emptyList(), Collections.singletonList(
                new FibUpdate(FibUpdate.Type.DELETE, deleteFibEntry)));

        replay(fibListener);

        router.processRouteUpdates(Collections.singletonList(
                new RouteUpdate(RouteUpdate.Type.DELETE, deleteRouteEntry)));

        verify(fibListener);
    }

    /**
     * Tests adding a route whose next hop is the local BGP speaker.
     */
    @Test
    public void testLocalRouteAdd() {
        // Construct a route entry, the next hop is the local BGP speaker
        RouteEntry routeEntry = new RouteEntry(
                Ip4Prefix.valueOf("1.1.1.0/24"),
                Ip4Address.valueOf("0.0.0.0"));

        // No methods on the FIB listener should be called
        replay(fibListener);

        // Call the processRouteUpdates() method in Router class
        RouteUpdate routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE,
                                                  routeEntry);
        router.processRouteUpdates(Collections.singletonList(routeUpdate));

        // Verify
        assertEquals(1, router.getRoutes4().size());
        assertTrue(router.getRoutes4().contains(routeEntry));
        verify(fibListener);
    }
}