pg: A Tunnel mode variant of a pg interface
Type: feature this allows VPP to simulate linux tun devices. Signed-off-by: Neale Ranns <neale@graphiant.com> Change-Id: I3adf38b49a254804370f78edd5d275d192fd00a6
This commit is contained in:
@ -333,6 +333,23 @@ validate_stream (pg_stream_t * s)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
pg_interface_get_input_node (pg_interface_t *pi)
|
||||||
|
{
|
||||||
|
switch (pi->mode)
|
||||||
|
{
|
||||||
|
case PG_MODE_ETHERNET:
|
||||||
|
return ("ethernet-input");
|
||||||
|
case PG_MODE_IP4:
|
||||||
|
return ("ip4-input");
|
||||||
|
case PG_MODE_IP6:
|
||||||
|
return ("ip6-input");
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT (0);
|
||||||
|
return ("ethernet-input");
|
||||||
|
}
|
||||||
|
|
||||||
static clib_error_t *
|
static clib_error_t *
|
||||||
new_stream (vlib_main_t * vm,
|
new_stream (vlib_main_t * vm,
|
||||||
unformat_input_t * input, vlib_cli_command_t * cmd)
|
unformat_input_t * input, vlib_cli_command_t * cmd)
|
||||||
@ -351,7 +368,7 @@ new_stream (vlib_main_t * vm,
|
|||||||
s.node_index = ~0;
|
s.node_index = ~0;
|
||||||
s.max_packet_bytes = s.min_packet_bytes = 64;
|
s.max_packet_bytes = s.min_packet_bytes = 64;
|
||||||
s.buffer_bytes = vlib_buffer_get_default_data_size (vm);
|
s.buffer_bytes = vlib_buffer_get_default_data_size (vm);
|
||||||
s.if_id = 0;
|
s.if_id = ~0;
|
||||||
s.n_max_frame = VLIB_FRAME_SIZE;
|
s.n_max_frame = VLIB_FRAME_SIZE;
|
||||||
pcap_file_name = 0;
|
pcap_file_name = 0;
|
||||||
|
|
||||||
@ -427,8 +444,15 @@ new_stream (vlib_main_t * vm,
|
|||||||
{
|
{
|
||||||
if (pcap_file_name != 0)
|
if (pcap_file_name != 0)
|
||||||
{
|
{
|
||||||
vlib_node_t *n =
|
vlib_node_t *n;
|
||||||
vlib_get_node_by_name (vm, (u8 *) "ethernet-input");
|
|
||||||
|
ASSERT (s.if_id != ~0);
|
||||||
|
|
||||||
|
if (s.if_id != ~0)
|
||||||
|
n = vlib_get_node_by_name (vm, (u8 *) pg_interface_get_input_node (
|
||||||
|
&pg->interfaces[s.if_id]));
|
||||||
|
else
|
||||||
|
n = vlib_get_node_by_name (vm, (u8 *) "ethernet-input");
|
||||||
s.node_index = n->index;
|
s.node_index = n->index;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -694,8 +718,8 @@ create_pg_if_cmd_fn (vlib_main_t * vm,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pg_interface_add_or_get (pg, if_id, gso_enabled, gso_size,
|
pg_interface_add_or_get (pg, if_id, gso_enabled, gso_size, coalesce_enabled,
|
||||||
coalesce_enabled);
|
PG_MODE_ETHERNET);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
unformat_free (line_input);
|
unformat_free (line_input);
|
||||||
|
@ -22,6 +22,13 @@ option version = "2.0.0";
|
|||||||
|
|
||||||
import "vnet/interface_types.api";
|
import "vnet/interface_types.api";
|
||||||
|
|
||||||
|
enum pg_interface_mode : u8
|
||||||
|
{
|
||||||
|
PG_API_MODE_ETHERNET = 0,
|
||||||
|
PG_API_MODE_IP4,
|
||||||
|
PG_API_MODE_IP6,
|
||||||
|
};
|
||||||
|
|
||||||
/** \brief PacketGenerator create interface request
|
/** \brief PacketGenerator create interface request
|
||||||
@param client_index - opaque cookie to identify the sender
|
@param client_index - opaque cookie to identify the sender
|
||||||
@param context - sender context, to match reply w/ request
|
@param context - sender context, to match reply w/ request
|
||||||
@ -37,6 +44,15 @@ define pg_create_interface
|
|||||||
bool gso_enabled;
|
bool gso_enabled;
|
||||||
u32 gso_size;
|
u32 gso_size;
|
||||||
};
|
};
|
||||||
|
define pg_create_interface_v2
|
||||||
|
{
|
||||||
|
u32 client_index;
|
||||||
|
u32 context;
|
||||||
|
vl_api_interface_index_t interface_id;
|
||||||
|
bool gso_enabled;
|
||||||
|
u32 gso_size;
|
||||||
|
vl_api_pg_interface_mode_t mode;
|
||||||
|
};
|
||||||
|
|
||||||
/** \brief PacketGenerator create interface response
|
/** \brief PacketGenerator create interface response
|
||||||
@param context - sender context, to match reply w/ request
|
@param context - sender context, to match reply w/ request
|
||||||
@ -48,6 +64,12 @@ define pg_create_interface_reply
|
|||||||
i32 retval;
|
i32 retval;
|
||||||
vl_api_interface_index_t sw_if_index;
|
vl_api_interface_index_t sw_if_index;
|
||||||
};
|
};
|
||||||
|
define pg_create_interface_v2_reply
|
||||||
|
{
|
||||||
|
u32 context;
|
||||||
|
i32 retval;
|
||||||
|
vl_api_interface_index_t sw_if_index;
|
||||||
|
};
|
||||||
|
|
||||||
/** \brief PacketGenerator interface enable/disable packet coalesce
|
/** \brief PacketGenerator interface enable/disable packet coalesce
|
||||||
@param client_index - opaque cookie to identify the sender
|
@param client_index - opaque cookie to identify the sender
|
||||||
|
@ -299,6 +299,13 @@ pg_free_edit_group (pg_stream_t * s)
|
|||||||
_vec_len (s->edit_groups) = i;
|
_vec_len (s->edit_groups) = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef enum pg_interface_mode_t_
|
||||||
|
{
|
||||||
|
PG_MODE_ETHERNET,
|
||||||
|
PG_MODE_IP4,
|
||||||
|
PG_MODE_IP6,
|
||||||
|
} pg_interface_mode_t;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
/* TX lock */
|
/* TX lock */
|
||||||
@ -316,6 +323,7 @@ typedef struct
|
|||||||
u32 gso_size;
|
u32 gso_size;
|
||||||
pcap_main_t pcap_main;
|
pcap_main_t pcap_main;
|
||||||
char *pcap_file_name;
|
char *pcap_file_name;
|
||||||
|
pg_interface_mode_t mode;
|
||||||
|
|
||||||
mac_address_t *allowed_mcast_macs;
|
mac_address_t *allowed_mcast_macs;
|
||||||
} pg_interface_t;
|
} pg_interface_t;
|
||||||
@ -373,9 +381,9 @@ void pg_interface_enable_disable_coalesce (pg_interface_t * pi, u8 enable,
|
|||||||
u32 tx_node_index);
|
u32 tx_node_index);
|
||||||
|
|
||||||
/* Find/create free packet-generator interface index. */
|
/* Find/create free packet-generator interface index. */
|
||||||
u32 pg_interface_add_or_get (pg_main_t * pg, uword stream_index,
|
u32 pg_interface_add_or_get (pg_main_t *pg, uword stream_index, u8 gso_enabled,
|
||||||
u8 gso_enabled, u32 gso_size,
|
u32 gso_size, u8 coalesce_enabled,
|
||||||
u8 coalesce_enabled);
|
pg_interface_mode_t mode);
|
||||||
|
|
||||||
always_inline pg_node_t *
|
always_inline pg_node_t *
|
||||||
pg_get_node (uword node_index)
|
pg_get_node (uword node_index)
|
||||||
|
@ -40,12 +40,13 @@
|
|||||||
|
|
||||||
#include <vlibapi/api_helper_macros.h>
|
#include <vlibapi/api_helper_macros.h>
|
||||||
|
|
||||||
|
#define foreach_pg_api_msg \
|
||||||
#define foreach_pg_api_msg \
|
_ (PG_CREATE_INTERFACE, pg_create_interface) \
|
||||||
_(PG_CREATE_INTERFACE, pg_create_interface) \
|
_ (PG_CREATE_INTERFACE_V2, pg_create_interface_v2) \
|
||||||
_(PG_CAPTURE, pg_capture) \
|
_ (PG_CAPTURE, pg_capture) \
|
||||||
_(PG_ENABLE_DISABLE, pg_enable_disable) \
|
_ (PG_ENABLE_DISABLE, pg_enable_disable) \
|
||||||
_(PG_INTERFACE_ENABLE_DISABLE_COALESCE, pg_interface_enable_disable_coalesce)
|
_ (PG_INTERFACE_ENABLE_DISABLE_COALESCE, \
|
||||||
|
pg_interface_enable_disable_coalesce)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vl_api_pg_create_interface_t_handler (vl_api_pg_create_interface_t * mp)
|
vl_api_pg_create_interface_t_handler (vl_api_pg_create_interface_t * mp)
|
||||||
@ -54,9 +55,9 @@ vl_api_pg_create_interface_t_handler (vl_api_pg_create_interface_t * mp)
|
|||||||
int rv = 0;
|
int rv = 0;
|
||||||
|
|
||||||
pg_main_t *pg = &pg_main;
|
pg_main_t *pg = &pg_main;
|
||||||
u32 pg_if_id = pg_interface_add_or_get (pg, ntohl (mp->interface_id),
|
u32 pg_if_id =
|
||||||
mp->gso_enabled,
|
pg_interface_add_or_get (pg, ntohl (mp->interface_id), mp->gso_enabled,
|
||||||
ntohl (mp->gso_size), 0);
|
ntohl (mp->gso_size), 0, PG_MODE_ETHERNET);
|
||||||
pg_interface_t *pi = pool_elt_at_index (pg->interfaces, pg_if_id);
|
pg_interface_t *pi = pool_elt_at_index (pg->interfaces, pg_if_id);
|
||||||
|
|
||||||
/* *INDENT-OFF* */
|
/* *INDENT-OFF* */
|
||||||
@ -67,6 +68,22 @@ vl_api_pg_create_interface_t_handler (vl_api_pg_create_interface_t * mp)
|
|||||||
/* *INDENT-ON* */
|
/* *INDENT-ON* */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vl_api_pg_create_interface_v2_t_handler (vl_api_pg_create_interface_v2_t *mp)
|
||||||
|
{
|
||||||
|
vl_api_pg_create_interface_v2_reply_t *rmp;
|
||||||
|
int rv = 0;
|
||||||
|
|
||||||
|
pg_main_t *pg = &pg_main;
|
||||||
|
u32 pg_if_id =
|
||||||
|
pg_interface_add_or_get (pg, ntohl (mp->interface_id), mp->gso_enabled,
|
||||||
|
ntohl (mp->gso_size), 0, (u8) mp->mode);
|
||||||
|
pg_interface_t *pi = pool_elt_at_index (pg->interfaces, pg_if_id);
|
||||||
|
|
||||||
|
REPLY_MACRO2 (VL_API_PG_CREATE_INTERFACE_V2_REPLY,
|
||||||
|
({ rmp->sw_if_index = ntohl (pi->sw_if_index); }));
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vl_api_pg_interface_enable_disable_coalesce_t_handler
|
vl_api_pg_interface_enable_disable_coalesce_t_handler
|
||||||
(vl_api_pg_interface_enable_disable_coalesce_t * mp)
|
(vl_api_pg_interface_enable_disable_coalesce_t * mp)
|
||||||
|
@ -229,9 +229,29 @@ pg_interface_enable_disable_coalesce (pg_interface_t * pi, u8 enable,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u8 *
|
||||||
|
format_pg_tun_tx_trace (u8 *s, va_list *args)
|
||||||
|
{
|
||||||
|
CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
|
||||||
|
CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
|
||||||
|
|
||||||
|
s = format (s, "PG: tunnel (no-encap)");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
VNET_HW_INTERFACE_CLASS (pg_tun_hw_interface_class) = {
|
||||||
|
.name = "PG-tun",
|
||||||
|
//.format_header = format_gre_header_with_length,
|
||||||
|
//.unformat_header = unformat_gre_header,
|
||||||
|
.build_rewrite = NULL,
|
||||||
|
//.update_adjacency = gre_update_adj,
|
||||||
|
.flags = VNET_HW_INTERFACE_CLASS_FLAG_P2P,
|
||||||
|
};
|
||||||
|
|
||||||
u32
|
u32
|
||||||
pg_interface_add_or_get (pg_main_t * pg, uword if_id, u8 gso_enabled,
|
pg_interface_add_or_get (pg_main_t *pg, uword if_id, u8 gso_enabled,
|
||||||
u32 gso_size, u8 coalesce_enabled)
|
u32 gso_size, u8 coalesce_enabled,
|
||||||
|
pg_interface_mode_t mode)
|
||||||
{
|
{
|
||||||
vnet_main_t *vnm = vnet_get_main ();
|
vnet_main_t *vnm = vnet_get_main ();
|
||||||
vlib_main_t *vm = vlib_get_main ();
|
vlib_main_t *vm = vlib_get_main ();
|
||||||
@ -262,8 +282,20 @@ pg_interface_add_or_get (pg_main_t * pg, uword if_id, u8 gso_enabled,
|
|||||||
hw_addr[1] = 0xfe;
|
hw_addr[1] = 0xfe;
|
||||||
|
|
||||||
pi->id = if_id;
|
pi->id = if_id;
|
||||||
ethernet_register_interface (vnm, pg_dev_class.index, i, hw_addr,
|
pi->mode = mode;
|
||||||
&pi->hw_if_index, pg_eth_flag_change);
|
|
||||||
|
switch (pi->mode)
|
||||||
|
{
|
||||||
|
case PG_MODE_ETHERNET:
|
||||||
|
ethernet_register_interface (vnm, pg_dev_class.index, i, hw_addr,
|
||||||
|
&pi->hw_if_index, pg_eth_flag_change);
|
||||||
|
break;
|
||||||
|
case PG_MODE_IP4:
|
||||||
|
case PG_MODE_IP6:
|
||||||
|
pi->hw_if_index = vnet_register_interface (
|
||||||
|
vnm, pg_dev_class.index, i, pg_tun_hw_interface_class.index, i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
hi = vnet_get_hw_interface (vnm, pi->hw_if_index);
|
hi = vnet_get_hw_interface (vnm, pi->hw_if_index);
|
||||||
if (gso_enabled)
|
if (gso_enabled)
|
||||||
{
|
{
|
||||||
@ -510,9 +542,9 @@ pg_stream_add (pg_main_t * pg, pg_stream_t * s_init)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Find an interface to use. */
|
/* Find an interface to use. */
|
||||||
s->pg_if_index =
|
s->pg_if_index = pg_interface_add_or_get (
|
||||||
pg_interface_add_or_get (pg, s->if_id, 0 /* gso_enabled */ ,
|
pg, s->if_id, 0 /* gso_enabled */, 0 /* gso_size */,
|
||||||
0 /* gso_size */ , 0 /* coalesce_enabled */ );
|
0 /* coalesce_enabled */, PG_MODE_ETHERNET);
|
||||||
|
|
||||||
if (s->sw_if_index[VLIB_RX] == ~0)
|
if (s->sw_if_index[VLIB_RX] == ~0)
|
||||||
{
|
{
|
||||||
|
@ -32,6 +32,7 @@ from vpp_sub_interface import VppSubInterface
|
|||||||
from vpp_lo_interface import VppLoInterface
|
from vpp_lo_interface import VppLoInterface
|
||||||
from vpp_bvi_interface import VppBviInterface
|
from vpp_bvi_interface import VppBviInterface
|
||||||
from vpp_papi_provider import VppPapiProvider
|
from vpp_papi_provider import VppPapiProvider
|
||||||
|
from vpp_papi import VppEnum
|
||||||
import vpp_papi
|
import vpp_papi
|
||||||
from vpp_papi.vpp_stats import VPPStats
|
from vpp_papi.vpp_stats import VPPStats
|
||||||
from vpp_papi.vpp_transport_socket import VppTransportSocketIOError
|
from vpp_papi.vpp_transport_socket import VppTransportSocketIOError
|
||||||
@ -915,7 +916,8 @@ class VppTestCase(CPUInterface, unittest.TestCase):
|
|||||||
cls._pcaps = []
|
cls._pcaps = []
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create_pg_interfaces(cls, interfaces, gso=0, gso_size=0):
|
def create_pg_interfaces_internal(cls, interfaces, gso=0, gso_size=0,
|
||||||
|
mode=None):
|
||||||
"""
|
"""
|
||||||
Create packet-generator interfaces.
|
Create packet-generator interfaces.
|
||||||
|
|
||||||
@ -925,12 +927,36 @@ class VppTestCase(CPUInterface, unittest.TestCase):
|
|||||||
"""
|
"""
|
||||||
result = []
|
result = []
|
||||||
for i in interfaces:
|
for i in interfaces:
|
||||||
intf = VppPGInterface(cls, i, gso, gso_size)
|
intf = VppPGInterface(cls, i, gso, gso_size, mode)
|
||||||
setattr(cls, intf.name, intf)
|
setattr(cls, intf.name, intf)
|
||||||
result.append(intf)
|
result.append(intf)
|
||||||
cls.pg_interfaces = result
|
cls.pg_interfaces = result
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_pg_ip4_interfaces(cls, interfaces, gso=0, gso_size=0):
|
||||||
|
pgmode = VppEnum.vl_api_pg_interface_mode_t
|
||||||
|
return cls.create_pg_interfaces_internal(interfaces, gso, gso_size,
|
||||||
|
pgmode.PG_API_MODE_IP4)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_pg_ip6_interfaces(cls, interfaces, gso=0, gso_size=0):
|
||||||
|
pgmode = VppEnum.vl_api_pg_interface_mode_t
|
||||||
|
return cls.create_pg_interfaces_internal(interfaces, gso, gso_size,
|
||||||
|
pgmode.PG_API_MODE_IP6)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_pg_interfaces(cls, interfaces, gso=0, gso_size=0):
|
||||||
|
pgmode = VppEnum.vl_api_pg_interface_mode_t
|
||||||
|
return cls.create_pg_interfaces_internal(interfaces, gso, gso_size,
|
||||||
|
pgmode.PG_API_MODE_ETHERNET)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_pg_ethernet_interfaces(cls, interfaces, gso=0, gso_size=0):
|
||||||
|
pgmode = VppEnum.vl_api_pg_interface_mode_t
|
||||||
|
return cls.create_pg_interfaces_internal(interfaces, gso, gso_size,
|
||||||
|
pgmode.PG_API_MODE_ETHERNET)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create_loopback_interfaces(cls, count):
|
def create_loopback_interfaces(cls, count):
|
||||||
"""
|
"""
|
||||||
|
98
test/test_pg.py
Normal file
98
test/test_pg.py
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
import scapy.compat
|
||||||
|
from scapy.packet import Raw
|
||||||
|
from scapy.layers.l2 import Ether
|
||||||
|
from scapy.layers.inet import IP, UDP
|
||||||
|
from scapy.layers.inet6 import IPv6
|
||||||
|
|
||||||
|
from framework import VppTestCase, VppTestRunner
|
||||||
|
|
||||||
|
|
||||||
|
class TestPgTun(VppTestCase):
|
||||||
|
""" PG Test Case """
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestPgTun, self).setUp()
|
||||||
|
|
||||||
|
# create 3 pg interfaces - one each ethernet, ip4-tun, ip6-tun.
|
||||||
|
self.create_pg_interfaces(range(0, 1))
|
||||||
|
self.pg_interfaces += self.create_pg_ip4_interfaces(range(1, 2))
|
||||||
|
self.pg_interfaces += self.create_pg_ip6_interfaces(range(2, 3))
|
||||||
|
|
||||||
|
for i in self.pg_interfaces:
|
||||||
|
i.admin_up()
|
||||||
|
|
||||||
|
for i in [self.pg0, self.pg1]:
|
||||||
|
i.config_ip4()
|
||||||
|
|
||||||
|
for i in [self.pg0, self.pg2]:
|
||||||
|
i.config_ip6()
|
||||||
|
|
||||||
|
self.pg0.resolve_arp()
|
||||||
|
self.pg0.resolve_ndp()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
for i in self.pg_interfaces:
|
||||||
|
i.unconfig_ip4()
|
||||||
|
i.admin_down()
|
||||||
|
super(TestPgTun, self).tearDown()
|
||||||
|
|
||||||
|
def test_pg_tun(self):
|
||||||
|
""" IP[46] Tunnel Mode PG """
|
||||||
|
|
||||||
|
#
|
||||||
|
# test that we can send and receive IP encap'd packets on the
|
||||||
|
# tun interfaces
|
||||||
|
#
|
||||||
|
N_PKTS = 31
|
||||||
|
|
||||||
|
# v4 tun to ethernet
|
||||||
|
p = (IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
|
||||||
|
UDP(sport=1234, dport=1234) /
|
||||||
|
Raw('0' * 48))
|
||||||
|
|
||||||
|
rxs = self.send_and_expect(self.pg1, p * N_PKTS, self.pg0)
|
||||||
|
for rx in rxs:
|
||||||
|
self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
|
||||||
|
self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
|
||||||
|
|
||||||
|
# v6 tun to ethernet
|
||||||
|
p = (IPv6(src=self.pg2.remote_ip6, dst=self.pg0.remote_ip6) /
|
||||||
|
UDP(sport=1234, dport=1234) /
|
||||||
|
Raw('0' * 48))
|
||||||
|
|
||||||
|
rxs = self.send_and_expect(self.pg2, p * N_PKTS, self.pg0)
|
||||||
|
for rx in rxs:
|
||||||
|
self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
|
||||||
|
self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
|
||||||
|
|
||||||
|
# eth to v4 tun
|
||||||
|
p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
|
||||||
|
IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
|
||||||
|
UDP(sport=1234, dport=1234) /
|
||||||
|
Raw('0' * 48))
|
||||||
|
|
||||||
|
rxs = self.send_and_expect(self.pg0, p * N_PKTS, self.pg1)
|
||||||
|
for rx in rxs:
|
||||||
|
rx = IP(rx)
|
||||||
|
self.assertFalse(rx.haslayer(Ether))
|
||||||
|
self.assertEqual(rx[IP].dst, self.pg1.remote_ip4)
|
||||||
|
|
||||||
|
# eth to v6 tun
|
||||||
|
p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
|
||||||
|
IPv6(src=self.pg0.remote_ip6, dst=self.pg2.remote_ip6) /
|
||||||
|
UDP(sport=1234, dport=1234) /
|
||||||
|
Raw('0' * 48))
|
||||||
|
|
||||||
|
rxs = self.send_and_expect(self.pg0, p * N_PKTS, self.pg2)
|
||||||
|
for rx in rxs:
|
||||||
|
rx = IPv6(rx)
|
||||||
|
self.assertFalse(rx.haslayer(Ether))
|
||||||
|
self.assertEqual(rx[IPv6].dst, self.pg2.remote_ip6)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main(testRunner=VppTestRunner)
|
@ -9,6 +9,7 @@ import scapy.compat
|
|||||||
from scapy.utils import wrpcap, rdpcap, PcapReader
|
from scapy.utils import wrpcap, rdpcap, PcapReader
|
||||||
from scapy.plist import PacketList
|
from scapy.plist import PacketList
|
||||||
from vpp_interface import VppInterface
|
from vpp_interface import VppInterface
|
||||||
|
from vpp_papi import VppEnum
|
||||||
|
|
||||||
from scapy.layers.l2 import Ether, ARP
|
from scapy.layers.l2 import Ether, ARP
|
||||||
from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6ND_NA,\
|
from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6ND_NA,\
|
||||||
@ -111,11 +112,11 @@ class VppPGInterface(VppInterface):
|
|||||||
self._out_history_counter += 1
|
self._out_history_counter += 1
|
||||||
return v
|
return v
|
||||||
|
|
||||||
def __init__(self, test, pg_index, gso, gso_size):
|
def __init__(self, test, pg_index, gso, gso_size, mode):
|
||||||
""" Create VPP packet-generator interface """
|
""" Create VPP packet-generator interface """
|
||||||
super().__init__(test)
|
super().__init__(test)
|
||||||
|
|
||||||
r = test.vapi.pg_create_interface(pg_index, gso, gso_size)
|
r = test.vapi.pg_create_interface_v2(pg_index, gso, gso_size, mode)
|
||||||
self.set_sw_if_index(r.sw_if_index)
|
self.set_sw_if_index(r.sw_if_index)
|
||||||
|
|
||||||
self._in_history_counter = 0
|
self._in_history_counter = 0
|
||||||
|
Reference in New Issue
Block a user