/* Test the working of the system router when it is configured to allow all
   * traffic (full mesh)
   */
  @Test
  public void testGetForwardingActionSystemRtr() throws Exception {
    expect(vRtrManager.findSubnetOwner(EasyMock.anyObject(IPV4Subnet.class)))
        .andReturn(null)
        .once();
    expect(vRtrManager.findSubnetOwner(EasyMock.anyObject(IPV4Subnet.class)))
        .andReturn("B|vrB")
        .times(1);
    replay(vRtrManager);

    /* System Router */
    VRouterImpl vrs = new VRouterImpl("rs", "system", vMac1, vRtrManager);
    vrs.createInterface("if1", null, "A|vrA", true);
    vrs.createInterface("if2", null, "B|vrB", true);
    vrs.createInterface("ifexternal", null, "external|vrX", true);

    VNS netVirtA1 = new VNS("A|netVirtA1");
    int ipA1, ipB1, ipX;
    ipA1 = IPv4.toIPv4Address("10.1.1.2");
    ipB1 = IPv4.toIPv4Address("10.1.2.2");
    ipX = IPv4.toIPv4Address("8.8.8.8");
    ForwardingAction action;

    /* Allow all communication */
    vrs.addRoutingRule(
        null,
        null,
        "10.0.0.0",
        "255.255.255.255",
        null,
        null,
        "10.0.0.0",
        "255.255.255.255",
        null,
        null,
        "permit");
    /* Testing for a silent host. The dest device entity is null */
    action = vrs.getForwardingAction("A|vrA", netVirtA1, ipA1, null, ipX);
    assertEquals(RoutingAction.FORWARD, action.getAction());
    assertEquals("external|vrX", action.getNextRtrName());
    assertEquals(ipX, action.getNextHopIp());
    assertEquals(null, action.getDstNetVirtName());
    assertEquals(0, action.getNewSrcMac());
    assertEquals(null, action.getNextHopGatewayPool());
    assertEquals(null, action.getNextHopGatewayPoolRouter());

    /* Inter tenant communication is allowed */
    action = vrs.getForwardingAction("A|vrA", netVirtA1, ipA1, null, ipB1);
    assertEquals(RoutingAction.FORWARD, action.getAction());
    assertEquals("B|vrB", action.getNextRtrName());
    assertEquals(ipB1, action.getNextHopIp());
    assertEquals(null, action.getDstNetVirtName());
    assertEquals(0, action.getNewSrcMac());
    assertEquals(null, action.getNextHopGatewayPool());
    assertEquals(null, action.getNextHopGatewayPoolRouter());

    /* Communication from external tenant is correctly routed */
    VNS netVirtX = new VNS("external|netVirtX");
    action = vrs.getForwardingAction("external|vrX", netVirtX, ipX, netVirtA1, ipA1);
    assertEquals(RoutingAction.FORWARD, action.getAction());
    assertEquals("A|vrA", action.getNextRtrName());
    assertEquals(ipA1, action.getNextHopIp());
    assertEquals(null, action.getDstNetVirtName());
    assertEquals(0, action.getNewSrcMac());
    assertEquals(null, action.getNextHopGatewayPool());
    assertEquals(null, action.getNextHopGatewayPoolRouter());

    verify(vRtrManager);
  }
  @Test
  public void testGetForwardingActionSilentHost() throws Exception {
    expect(vRtrManager.findSubnetOwner(EasyMock.anyObject(IPV4Subnet.class)))
        .andReturn("t2|r2")
        .times(2);
    expect(vRtrManager.findSubnetOwner(EasyMock.anyObject(IPV4Subnet.class)))
        .andReturn(null)
        .once();
    vRtrManager.addSubnetOwner(
        EasyMock.anyObject(IPV4Subnet.class), EasyMock.anyObject(String.class));
    expectLastCall().times(3);
    vRtrManager.addIfaceIpMap(EasyMock.anyInt(), EasyMock.anyObject(VRouterInterface.class));
    expectLastCall().anyTimes();
    replay(vRtrManager);

    vr.createInterface("if1", "t1|netVirt1", null, true);
    vr.createInterface("if2", "t1|netVirt2", null, true);
    vr.createInterface("ifs", null, "system|rs", true);
    vr.assignInterfaceAddr("if1", "10.1.1.1", "0.0.0.255");
    vr.assignInterfaceAddr("if2", "10.1.2.1", "0.0.0.255");

    VRouterImpl vr2 = new VRouterImpl("r2", "t2", vMac1, vRtrManager);
    vr2.createInterface("if1", "t2|netVirt1", null, true);
    vr2.createInterface("if2", "t2|netVirt2", null, true);
    vr2.createInterface("ifs", null, "system|rs", true);
    vr2.assignInterfaceAddr("if1", "10.2.1.1", "0.0.0.255");

    /* External tenant router */
    VRouterImpl vrx = new VRouterImpl("rx", "tx", vMac1, vRtrManager);
    vrx.createInterface("if1", "tx|netVirtx", null, true);
    vrx.createInterface("ifs", null, "system|rs", true);

    /* System Router */
    VRouterImpl vrs = new VRouterImpl("rs", "system", vMac1, vRtrManager);
    vrs.createInterface("if1", null, "t1|r1", true);
    vrs.createInterface("if2", null, "t2|r2", true);
    vrs.createInterface("ifx", null, "tx|rx", true);

    VNS netVirtA1 = new VNS("t1|netVirt1");
    int ip1, ip2, ip3;
    ip1 = IPv4.toIPv4Address("10.1.1.2");
    ip2 = IPv4.toIPv4Address("10.1.2.2");
    ip3 = IPv4.toIPv4Address("10.2.1.2");
    ForwardingAction action;

    /* Allow host 10.1.1.2 to talk to all other hosts */
    vr.addRoutingRule(
        null,
        null,
        "10.1.1.2",
        "0.0.0.0",
        null,
        null,
        "255.255.255.255",
        "255.255.255.255",
        null,
        null,
        "permit");
    /* Testing for a silent host. The dest device entity is null */
    action = vr.getForwardingAction("t1|netVirt1", netVirtA1, ip1, null, ip2);
    assertEquals(RoutingAction.FORWARD, action.getAction());
    assertEquals(null, action.getNextRtrName());
    assertEquals(ip2, action.getNextHopIp());
    assertEquals("t1|netVirt2", action.getDstNetVirtName());
    assertEquals(vMac1.longValue(), action.getNewSrcMac());
    assertEquals(null, action.getNextHopGatewayPool());
    assertEquals(null, action.getNextHopGatewayPoolRouter());

    action = vr.getForwardingAction("t1|netVirt1", netVirtA1, ip1, null, ip3);
    assertEquals(RoutingAction.FORWARD, action.getAction());
    assertEquals("system|rs", action.getNextRtrName());
    assertEquals(ip3, action.getNextHopIp());
    assertEquals(null, action.getDstNetVirtName());
    assertEquals(0, action.getNewSrcMac());
    assertEquals(null, action.getNextHopGatewayPool());
    assertEquals(null, action.getNextHopGatewayPoolRouter());

    /* Allow all hosts in NetVirtA1 subnet to talk to any other hosts */
    vrs.addRoutingRule(
        null,
        null,
        "10.1.1.0",
        "0.0.0.255",
        null,
        null,
        "0.0.0.0",
        "255.255.255.255",
        null,
        null,
        "permit");
    action = vrs.getForwardingAction("t1|r1", netVirtA1, ip1, null, ip3);
    assertEquals(RoutingAction.FORWARD, action.getAction());
    assertEquals("t2|r2", action.getNextRtrName());
    assertEquals(ip3, action.getNextHopIp());
    assertEquals(null, action.getDstNetVirtName());
    assertEquals(0, action.getNewSrcMac());
    assertEquals(null, action.getNextHopGatewayPool());
    assertEquals(null, action.getNextHopGatewayPoolRouter());

    /* Send a packet to an unknown subnet and see that it is dropped
     * Note that we have set the vRtrManager object to return null for the
     * call to findSubnetOwner after the second time.
     */
    ip3 = IPv4.toIPv4Address("192.168.0.1");
    action = vrs.getForwardingAction("t1|r1", netVirtA1, ip1, null, ip3);
    assertEquals(RoutingAction.DROP, action.getAction());

    verify(vRtrManager);
  }