Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 11a2212087 | |||
| 54f8aff02a | |||
| 9330de53eb | |||
| d004ecdb57 | |||
| b12b3c6b03 | |||
| 6bd1c77fdc | |||
| dd3d991606 | |||
| ded6dbdb29 | |||
| 2e591554b8 | |||
| fa065f96d1 | |||
| 3d2d96e554 | |||
| de569048a5 | |||
| 5f48784da3 | |||
| 9479838d08 | |||
| ddb39ff0fd | |||
| 0b374922d2 | |||
| 66b80310fb |
@@ -122,7 +122,7 @@ ifeq ($(OS_ID),fedora)
|
||||
RPM_DEPENDS_GROUPS = 'C Development Tools and Libraries'
|
||||
else ifeq ($(OS_ID)-$(OS_VERSION_ID),centos-8)
|
||||
RPM_DEPENDS += yum-utils
|
||||
RPM_DEPENDS += compat-openssl10
|
||||
RPM_DEPENDS += compat-openssl10 openssl-devel
|
||||
RPM_DEPENDS += python2-devel python36-devel python3-ply
|
||||
RPM_DEPENDS += python3-virtualenv python3-jsonschema
|
||||
RPM_DEPENDS += cmake
|
||||
|
||||
+672
-1
File diff suppressed because it is too large
Load Diff
Vendored
+3
@@ -39,6 +39,7 @@ define rdma-core_config_cmds
|
||||
$(CMAKE) -G Ninja $(rdma-core_src_dir) \
|
||||
-DENABLE_STATIC=1 -DENABLE_RESOLVE_NEIGH=0 -DNO_PYVERBS=1 -DENABLE_VALGRIND=0\
|
||||
-DCMAKE_BUILD_TYPE=$(RDMA_BUILD_TYPE) -DCMAKE_INSTALL_PREFIX=$(rdma-core_install_dir) \
|
||||
-DCMAKE_INSTALL_LIBDIR=lib \
|
||||
-DCMAKE_C_FLAGS='-fPIC -fvisibility=hidden' > $(rdma-core_config_log)
|
||||
endef
|
||||
|
||||
@@ -52,6 +53,8 @@ define rdma-core_install_cmds
|
||||
find $(rdma-core_install_dir) -name '*.a' -exec mv -v {} $(rdma-core_install_dir)/lib \; >> $(rdma-core_install_log)
|
||||
rmdir -v $(rdma-core_install_dir)/util $(rdma-core_install_dir)/lib/statics >> $(rdma-core_install_log)
|
||||
sed '/Libs.private:/ s/$$/ -lrdma_util -lccan/' -i $(rdma-core_install_dir)/lib/pkgconfig/libibverbs.pc
|
||||
sed '/Libs.private:/ s/ \S*\(rdmav25\)\S*//g' -i $(rdma-core_install_dir)/lib/pkgconfig/libibverbs.pc
|
||||
sed '/Libs.private:/ s/-lefa//g' -i $(rdma-core_install_dir)/lib/pkgconfig/libibverbs.pc
|
||||
endef
|
||||
|
||||
$(eval $(call package,rdma-core))
|
||||
|
||||
@@ -0,0 +1,232 @@
|
||||
From 7b44e3f10ac886eaece0ee3ed217ba7219ec41c1 Mon Sep 17 00:00:00 2001
|
||||
From: Robin Zhang <robinx.zhang@intel.com>
|
||||
Date: Mon, 19 Apr 2021 03:05:39 +0000
|
||||
Subject: [PATCH] net/iavf: deprecate i40evf pmd
|
||||
|
||||
The i40evf PMD will be deprecated, iavf will be the only VF driver for
|
||||
Intel 700 serial (i40e) NIC family. To reach this, there will be 2 steps:
|
||||
|
||||
Step 1: iavf will be the default VF driver, while i40evf still can be
|
||||
selected by devarg: "driver=i40evf".
|
||||
This is covered by this patch, which include:
|
||||
1) add all 700 serial NIC VF device ID into iavf PMD
|
||||
2) skip probe if devargs contain "driver=i40evf" in iavf
|
||||
3) continue probe if devargs contain "driver=i40evf" in i40evf
|
||||
|
||||
Step 2: i40evf and related devarg are removed, this will happen at DPDK
|
||||
21.11
|
||||
|
||||
Between step 1 and step 2, no new feature will be added into i40evf except
|
||||
bug fix.
|
||||
|
||||
Signed-off-by: Robin Zhang <robinx.zhang@intel.com>
|
||||
Acked-by: Qi Zhang <qi.z.zhang@intel.com>
|
||||
Acked-by: Ferruh Yigit <ferruh.yigit@intel.com>
|
||||
Acked-by: Beilei Xing <beilei.xing@intel.com>
|
||||
---
|
||||
doc/guides/nics/intel_vf.rst | 6 +++
|
||||
doc/guides/rel_notes/deprecation.rst | 8 ++++
|
||||
drivers/common/iavf/iavf_devids.h | 2 +
|
||||
drivers/net/i40e/i40e_ethdev_vf.c | 45 ++++++++++++++++++++++
|
||||
drivers/net/iavf/iavf_ethdev.c | 57 +++++++++++++++++++++++++++-
|
||||
5 files changed, 116 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/doc/guides/nics/intel_vf.rst b/doc/guides/nics/intel_vf.rst
|
||||
index 529ff4a955..fcea8151bf 100644
|
||||
--- a/doc/guides/nics/intel_vf.rst
|
||||
+++ b/doc/guides/nics/intel_vf.rst
|
||||
@@ -88,6 +88,12 @@ For more detail on SR-IOV, please refer to the following documents:
|
||||
assignment in hypervisor. Take qemu for example, the device assignment should carry the IAVF device id (0x1889) like
|
||||
``-device vfio-pci,x-pci-device-id=0x1889,host=03:0a.0``.
|
||||
|
||||
+ Starting from DPDK 21.05, the default VF driver for Intel® 700 Series Ethernet Controller will be IAVF. No new feature
|
||||
+ will be added into i40evf except bug fix until it's removed in DPDK 21.11. Between DPDK 21.05 and 21.11, by using the
|
||||
+ ``devargs`` option ``driver=i40evf``, i40evf PMD still can be used on Intel® 700 Series Ethernet Controller, for example::
|
||||
+
|
||||
+ -a 81:02.0,driver=i40evf
|
||||
+
|
||||
When IAVF is backed by an Intel® E810 device, the "Protocol Extraction" feature which is supported by ice PMD is also
|
||||
available for IAVF PMD. The same devargs with the same parameters can be applied to IAVF PMD, for detail please reference
|
||||
the section ``Protocol extraction for per queue`` of ice.rst.
|
||||
diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
|
||||
index 82c1a90a37..ea41be51a7 100644
|
||||
--- a/doc/guides/rel_notes/deprecation.rst
|
||||
+++ b/doc/guides/rel_notes/deprecation.rst
|
||||
@@ -125,3 +125,11 @@ Deprecation Notices
|
||||
* cmdline: ``cmdline`` structure will be made opaque to hide platform-specific
|
||||
content. On Linux and FreeBSD, supported prior to DPDK 20.11,
|
||||
original structure will be kept until DPDK 21.11.
|
||||
+
|
||||
+* i40e: As there are both i40evf and iavf pmd, the functions of them are
|
||||
+ duplicated. And now more and more advanced features are developed on iavf.
|
||||
+ To keep consistent with kernel driver's name
|
||||
+ (https://patchwork.ozlabs.org/patch/970154/), i40evf is no need to maintain.
|
||||
+ Starting from 21.05, the default VF driver of i40e will be iavf, but i40evf
|
||||
+ can still be used if users specify the devarg "driver=i40evf". I40evf will
|
||||
+ be deleted in DPDK 21.11.
|
||||
diff --git a/drivers/common/iavf/iavf_devids.h b/drivers/common/iavf/iavf_devids.h
|
||||
index 722c2e4f49..0f98375a09 100644
|
||||
--- a/drivers/common/iavf/iavf_devids.h
|
||||
+++ b/drivers/common/iavf/iavf_devids.h
|
||||
@@ -13,5 +13,7 @@
|
||||
#define IAVF_DEV_ID_VF_HV 0x1571
|
||||
#define IAVF_DEV_ID_ADAPTIVE_VF 0x1889
|
||||
#define IAVF_DEV_ID_X722_VF 0x37CD
|
||||
+#define IAVF_DEV_ID_X722_A0_VF 0x374D
|
||||
+
|
||||
|
||||
#endif /* _IAVF_DEVIDS_H_ */
|
||||
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
|
||||
index 2909b4d894..b5706a6a7f 100644
|
||||
--- a/drivers/net/i40e/i40e_ethdev_vf.c
|
||||
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
|
||||
@@ -1656,9 +1656,53 @@ i40evf_dev_uninit(struct rte_eth_dev *eth_dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int
|
||||
+i40evf_check_driver_handler(__rte_unused const char *key,
|
||||
+ const char *value, __rte_unused void *opaque)
|
||||
+{
|
||||
+ if (strcmp(value, "i40evf"))
|
||||
+ return -1;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+i40evf_driver_selected(struct rte_devargs *devargs)
|
||||
+{
|
||||
+ struct rte_kvargs *kvlist;
|
||||
+ const char *key = "driver";
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ if (devargs == NULL)
|
||||
+ return 0;
|
||||
+
|
||||
+ kvlist = rte_kvargs_parse(devargs->args, NULL);
|
||||
+ if (kvlist == NULL)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (!rte_kvargs_count(kvlist, key))
|
||||
+ goto exit;
|
||||
+
|
||||
+ /* i40evf driver selected when there's a key-value pair:
|
||||
+ * driver=i40evf
|
||||
+ */
|
||||
+ if (rte_kvargs_process(kvlist, key,
|
||||
+ i40evf_check_driver_handler, NULL) < 0)
|
||||
+ goto exit;
|
||||
+
|
||||
+ ret = 1;
|
||||
+
|
||||
+exit:
|
||||
+ rte_kvargs_free(kvlist);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static int eth_i40evf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
|
||||
struct rte_pci_device *pci_dev)
|
||||
{
|
||||
+ if (!i40evf_driver_selected(pci_dev->device.devargs))
|
||||
+ return 1;
|
||||
+
|
||||
return rte_eth_dev_pci_generic_probe(pci_dev,
|
||||
sizeof(struct i40e_adapter), i40evf_dev_init);
|
||||
}
|
||||
@@ -1681,6 +1725,7 @@ static struct rte_pci_driver rte_i40evf_pmd = {
|
||||
RTE_PMD_REGISTER_PCI(net_i40e_vf, rte_i40evf_pmd);
|
||||
RTE_PMD_REGISTER_PCI_TABLE(net_i40e_vf, pci_id_i40evf_map);
|
||||
RTE_PMD_REGISTER_KMOD_DEP(net_i40e_vf, "* igb_uio | vfio-pci");
|
||||
+RTE_PMD_REGISTER_PARAM_STRING(net_i40e_vf, "driver=i40evf");
|
||||
|
||||
static int
|
||||
i40evf_dev_configure(struct rte_eth_dev *dev)
|
||||
diff --git a/drivers/net/iavf/iavf_ethdev.c b/drivers/net/iavf/iavf_ethdev.c
|
||||
index 4d37722022..721cdcc14e 100644
|
||||
--- a/drivers/net/iavf/iavf_ethdev.c
|
||||
+++ b/drivers/net/iavf/iavf_ethdev.c
|
||||
@@ -127,6 +127,10 @@ static int iavf_set_mc_addr_list(struct rte_eth_dev *dev,
|
||||
|
||||
static const struct rte_pci_id pci_id_iavf_map[] = {
|
||||
{ RTE_PCI_DEVICE(IAVF_INTEL_VENDOR_ID, IAVF_DEV_ID_ADAPTIVE_VF) },
|
||||
+ { RTE_PCI_DEVICE(IAVF_INTEL_VENDOR_ID, IAVF_DEV_ID_VF) },
|
||||
+ { RTE_PCI_DEVICE(IAVF_INTEL_VENDOR_ID, IAVF_DEV_ID_VF_HV) },
|
||||
+ { RTE_PCI_DEVICE(IAVF_INTEL_VENDOR_ID, IAVF_DEV_ID_X722_VF) },
|
||||
+ { RTE_PCI_DEVICE(IAVF_INTEL_VENDOR_ID, IAVF_DEV_ID_X722_A0_VF) },
|
||||
{ .vendor_id = 0, /* sentinel */ },
|
||||
};
|
||||
|
||||
@@ -2331,10 +2335,59 @@ iavf_dcf_cap_selected(struct rte_devargs *devargs)
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static int
|
||||
+iavf_drv_i40evf_check_handler(__rte_unused const char *key,
|
||||
+ const char *value, __rte_unused void *opaque)
|
||||
+{
|
||||
+ if (strcmp(value, "i40evf"))
|
||||
+ return -1;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+iavf_drv_i40evf_selected(struct rte_devargs *devargs, uint16_t device_id)
|
||||
+{
|
||||
+ struct rte_kvargs *kvlist;
|
||||
+ const char *key = "driver";
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ if (device_id != IAVF_DEV_ID_VF &&
|
||||
+ device_id != IAVF_DEV_ID_VF_HV &&
|
||||
+ device_id != IAVF_DEV_ID_X722_VF &&
|
||||
+ device_id != IAVF_DEV_ID_X722_A0_VF)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (devargs == NULL)
|
||||
+ return 0;
|
||||
+
|
||||
+ kvlist = rte_kvargs_parse(devargs->args, NULL);
|
||||
+ if (kvlist == NULL)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (!rte_kvargs_count(kvlist, key))
|
||||
+ goto exit;
|
||||
+
|
||||
+ /* i40evf driver selected when there's a key-value pair:
|
||||
+ * driver=i40evf
|
||||
+ */
|
||||
+ if (rte_kvargs_process(kvlist, key,
|
||||
+ iavf_drv_i40evf_check_handler, NULL) < 0)
|
||||
+ goto exit;
|
||||
+
|
||||
+ ret = 1;
|
||||
+
|
||||
+exit:
|
||||
+ rte_kvargs_free(kvlist);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static int eth_iavf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
|
||||
struct rte_pci_device *pci_dev)
|
||||
{
|
||||
- if (iavf_dcf_cap_selected(pci_dev->device.devargs))
|
||||
+ if (iavf_dcf_cap_selected(pci_dev->device.devargs) ||
|
||||
+ iavf_drv_i40evf_selected(pci_dev->device.devargs,
|
||||
+ pci_dev->id.device_id))
|
||||
return 1;
|
||||
|
||||
return rte_eth_dev_pci_generic_probe(pci_dev,
|
||||
@@ -2357,7 +2410,7 @@ static struct rte_pci_driver rte_iavf_pmd = {
|
||||
RTE_PMD_REGISTER_PCI(net_iavf, rte_iavf_pmd);
|
||||
RTE_PMD_REGISTER_PCI_TABLE(net_iavf, pci_id_iavf_map);
|
||||
RTE_PMD_REGISTER_KMOD_DEP(net_iavf, "* igb_uio | vfio-pci");
|
||||
-RTE_PMD_REGISTER_PARAM_STRING(net_iavf, "cap=dcf");
|
||||
+RTE_PMD_REGISTER_PARAM_STRING(net_iavf, "cap=dcf driver=i40evf");
|
||||
RTE_LOG_REGISTER(iavf_logtype_init, pmd.net.iavf.init, NOTICE);
|
||||
RTE_LOG_REGISTER(iavf_logtype_driver, pmd.net.iavf.driver, NOTICE);
|
||||
#ifdef RTE_LIBRTE_IAVF_DEBUG_RX
|
||||
--
|
||||
2.20.1
|
||||
|
||||
@@ -20,3 +20,4 @@ extensive list, but should give a sampling of the many features contained in FD.
|
||||
networksim
|
||||
webapp
|
||||
container_test
|
||||
trafficgen
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
Vpp Stateless Traffic Generation
|
||||
================================
|
||||
|
||||
It's simple to configure vpp as a high-performance stateless traffic
|
||||
generator. A couple of vpp worker threads running on an older system
|
||||
can easily generate 20 MPPS' worth of traffic.
|
||||
|
||||
In the configurations shown below, we connect a vpp traffic generator
|
||||
and a vpp UUT using two 40 gigabit ethernet ports on each system:
|
||||
|
||||
```
|
||||
+-------------------+ +-------------------+
|
||||
| traffic generator | | UUT |
|
||||
| port 0 | <=======> | port 0 |
|
||||
| 192.168.40.2/24 | | 192.168.40.1/24 |
|
||||
+-------------------+ +-------------------+
|
||||
|
||||
+-------------------+ +-------------------+
|
||||
| traffic generator | | UUT |
|
||||
| port 1 | <=======> | port 1 |
|
||||
| 192.168.41.2/24 | | 192.168.41.1/24 |
|
||||
+-------------------+ +-------------------+
|
||||
```
|
||||
|
||||
Traffic Generator Setup Script
|
||||
------------------------------
|
||||
|
||||
```
|
||||
set int ip address FortyGigabitEthernet2/0/0 192.168.40.2/24
|
||||
set int ip address FortyGigabitEthernet2/0/1 192.168.41.2/24
|
||||
set int state FortyGigabitEthernet2/0/0 up
|
||||
set int state FortyGigabitEthernet2/0/1 up
|
||||
|
||||
comment { send traffic to the VPP UUT }
|
||||
|
||||
packet-generator new {
|
||||
name worker0
|
||||
worker 0
|
||||
limit 0
|
||||
rate 1.2e7
|
||||
size 128-128
|
||||
tx-interface FortyGigabitEthernet2/0/0
|
||||
node FortyGigabitEthernet2/0/0-output
|
||||
data { IP4: 1.2.40 -> 3cfd.fed0.b6c8
|
||||
UDP: 192.168.40.10 -> 192.168.50.10
|
||||
UDP: 1234 -> 2345
|
||||
incrementing 114
|
||||
}
|
||||
}
|
||||
|
||||
packet-generator new {
|
||||
name worker1
|
||||
worker 1
|
||||
limit 0
|
||||
rate 1.2e7
|
||||
size 128-128
|
||||
tx-interface FortyGigabitEthernet2/0/1
|
||||
node FortyGigabitEthernet2/0/1-output
|
||||
data { IP4: 1.2.4 -> 3cfd.fed0.b6c9
|
||||
UDP: 192.168.41.10 -> 192.168.51.10
|
||||
UDP: 1234 -> 2345
|
||||
incrementing 114
|
||||
}
|
||||
}
|
||||
|
||||
comment { delete return traffic on sight }
|
||||
|
||||
ip route add 192.168.50.0/24 via drop
|
||||
ip route add 192.168.51.0/24 via drop
|
||||
```
|
||||
|
||||
Note 1: the destination MAC addresses shown in the configuration (e.g.
|
||||
3cfd.fed0.b6c8 and 3cfd.fed0.b6c9) **must** match the vpp UUT port MAC
|
||||
addresses.
|
||||
|
||||
Note 2: this script assumes that /etc/vpp/startup.conf and/or the
|
||||
command-line in use specifies (at least) two worker threads. Uncomment
|
||||
"workers 2" in the cpu configuration section of /etc/vpp/startup.conf:
|
||||
|
||||
```
|
||||
## Specify a number of workers to be created
|
||||
## Workers are pinned to N consecutive CPU cores while skipping "skip-cores" CPU core(s)
|
||||
## and main thread's CPU core
|
||||
workers 2
|
||||
```
|
||||
|
||||
Any plausible packet generator script - including one which replays
|
||||
pcap captures - can be used.
|
||||
|
||||
|
||||
UUT Setup Script
|
||||
----------------
|
||||
|
||||
The vpp UUT uses a couple of static routes to forward traffic back to
|
||||
the traffic generator:
|
||||
|
||||
```
|
||||
set int ip address FortyGigabitEthernet2/0/0 192.168.40.1/24
|
||||
set int ip address FortyGigabitEthernet2/0/1 192.168.41.1/24
|
||||
set int state FortyGigabitEthernet2/0/0 up
|
||||
set int state FortyGigabitEthernet2/0/1 up
|
||||
|
||||
ip route add 192.168.50.10/32 via 192.168.41.2
|
||||
ip route add 192.168.51.10/32 via 192.168.40.2
|
||||
```
|
||||
@@ -19,4 +19,5 @@ Programming notes for developers.
|
||||
- @subpage handoff_queue_demo_plugin
|
||||
- @subpage lcov_code_coverage
|
||||
- @subpage mdata_doc
|
||||
- @subpage mempreload_doc
|
||||
|
||||
|
||||
@@ -29,3 +29,5 @@ Several modules provide operational, dataplane-user focused documentation.
|
||||
- @subpage srv6_doc
|
||||
- @subpage vcl_ldpreload_doc
|
||||
- @subpage vmxnet3_doc
|
||||
- @subpage af_xdp_doc
|
||||
- @subpage wireguard_plugin_doc
|
||||
|
||||
@@ -47,8 +47,8 @@ struct avf_ip4_psh
|
||||
|
||||
struct avf_ip6_psh
|
||||
{
|
||||
u32 src[4];
|
||||
u32 dst[4];
|
||||
ip6_address_t src;
|
||||
ip6_address_t dst;
|
||||
u32 l4len;
|
||||
u32 proto;
|
||||
};
|
||||
@@ -67,7 +67,7 @@ avf_tx_prepare_cksum (vlib_buffer_t * b, u8 is_tso)
|
||||
u32 is_ip6 = b->flags & VNET_BUFFER_F_IS_IP6;
|
||||
ASSERT (!is_tcp || !is_udp);
|
||||
ASSERT (is_ip4 || is_ip6);
|
||||
i16 l2_hdr_offset = vnet_buffer (b)->l2_hdr_offset;
|
||||
i16 l2_hdr_offset = b->current_data;
|
||||
i16 l3_hdr_offset = vnet_buffer (b)->l3_hdr_offset;
|
||||
i16 l4_hdr_offset = vnet_buffer (b)->l4_hdr_offset;
|
||||
u16 l2_len = l3_hdr_offset - l2_hdr_offset;
|
||||
@@ -113,8 +113,8 @@ avf_tx_prepare_cksum (vlib_buffer_t * b, u8 is_tso)
|
||||
else
|
||||
{
|
||||
struct avf_ip6_psh psh = { 0 };
|
||||
clib_memcpy_fast (&psh.src, &ip6->src_address, 16);
|
||||
clib_memcpy_fast (&psh.dst, &ip6->dst_address, 16);
|
||||
psh.src = ip6->src_address;
|
||||
psh.dst = ip6->dst_address;
|
||||
psh.proto = clib_host_to_net_u32 ((u32) ip6->protocol);
|
||||
psh.l4len = is_tso ? 0 : ip6->payload_length;
|
||||
sum = ~ip_csum (&psh, sizeof (psh));
|
||||
@@ -156,9 +156,8 @@ avf_tx_fill_ctx_desc (vlib_main_t * vm, avf_txq_t * txq, avf_tx_desc_t * d,
|
||||
/* Acquire a reference on the placeholder buffer */
|
||||
ctx_ph->ref_count++;
|
||||
|
||||
u16 l234hdr_sz =
|
||||
vnet_buffer (b)->l4_hdr_offset -
|
||||
vnet_buffer (b)->l2_hdr_offset + vnet_buffer2 (b)->gso_l4_hdr_sz;
|
||||
u16 l234hdr_sz = vnet_buffer (b)->l4_hdr_offset - b->current_data +
|
||||
vnet_buffer2 (b)->gso_l4_hdr_sz;
|
||||
u16 tlen = vlib_buffer_length_in_chain (vm, b) - l234hdr_sz;
|
||||
d[0].qword[0] = 0;
|
||||
d[0].qword[1] = AVF_TXD_DTYP_CTX | AVF_TXD_CTX_CMD_TSO
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <vlib/vmbus/vmbus.h>
|
||||
|
||||
#include <rte_ring.h>
|
||||
#include <rte_vect.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -1527,6 +1528,10 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
|
||||
ret = rte_eal_init (vec_len (conf->eal_init_args),
|
||||
(char **) conf->eal_init_args);
|
||||
|
||||
/* enable the AVX-512 vPMDs in DPDK */
|
||||
if (clib_cpu_supports_avx512_bitalg ())
|
||||
rte_vect_set_max_simd_bitwidth (RTE_VECT_SIMD_512);
|
||||
|
||||
/* lazy umount hugepages */
|
||||
umount2 ((char *) huge_dir_path, MNT_DETACH);
|
||||
rmdir ((char *) huge_dir_path);
|
||||
|
||||
@@ -366,6 +366,10 @@ slow_path_ed (snat_main_t * sm,
|
||||
ip4_address_t sm_addr;
|
||||
u16 sm_port;
|
||||
u32 sm_fib_index;
|
||||
|
||||
ctx.now = now;
|
||||
ctx.thread_index = thread_index;
|
||||
|
||||
/* First try to match static mapping by local address and port */
|
||||
if (snat_static_mapping_match
|
||||
(sm, l_addr, l_port, rx_fib_index, nat_proto, &sm_addr, &sm_port,
|
||||
@@ -458,8 +462,6 @@ slow_path_ed (snat_main_t * sm,
|
||||
clib_bihash_kv_16_8_t in2out_ed_kv;
|
||||
init_ed_kv (&in2out_ed_kv, l_addr, l_port, r_addr, r_port, rx_fib_index,
|
||||
proto, thread_index, s - tsm->sessions);
|
||||
ctx.now = now;
|
||||
ctx.thread_index = thread_index;
|
||||
if (clib_bihash_add_or_overwrite_stale_16_8 (&tsm->in2out_ed, &in2out_ed_kv,
|
||||
nat44_i2o_ed_is_idle_session_cb,
|
||||
&ctx))
|
||||
|
||||
@@ -974,7 +974,7 @@ rdma_device_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
n_rx_packets, bc);
|
||||
n_rx_bytes =
|
||||
rdma_device_mlx5dv_fast_input (vm, rxq, bufs, mask, &bt, to_next,
|
||||
n_rx_packets, bc, ~1);
|
||||
n_rx_packets, bc, ~0);
|
||||
|
||||
/* If there are chained buffers, some of the head buffers have a current length
|
||||
higher than buf_sz: it needs to be fixed */
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Wireguard vpp-plugin
|
||||
# Wireguard vpp-plugin {#wireguard_plugin_doc}
|
||||
|
||||
## Overview
|
||||
This plugin is an implementation of [wireguard protocol](https://www.wireguard.com/) for VPP. It allows one to create secure VPN tunnels.
|
||||
|
||||
@@ -30,6 +30,11 @@ TAG=$(echo ${vstring} | cut -d- -f1 | sed -e 's/^v//')
|
||||
ADD=$(echo ${vstring} | cut -s -d- -f2)
|
||||
POINT=$(echo ${TAG} | cut -d. -f3)
|
||||
|
||||
# during make pkg-rpm vstring ends up being vXX.YY, which is not what we expect. Fix it up.
|
||||
if [ -z "${ADD}" ]; then
|
||||
ADD="0"
|
||||
fi
|
||||
|
||||
# if this is a "implicit zeroth" release (e.g. 19.08), check if we need to add ".0"
|
||||
# to fix the artifact versioning sorting
|
||||
if [ -z "${POINT}" ]; then
|
||||
|
||||
+18
-4
@@ -40,6 +40,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <vlib/vlib.h>
|
||||
#include <vnet/vnet.h>
|
||||
|
||||
typedef struct _vlib_node_march_variant
|
||||
{
|
||||
@@ -89,9 +90,9 @@ unformat_vlib_node_variant (unformat_input_t * input, va_list * args)
|
||||
}
|
||||
|
||||
static_always_inline void
|
||||
vlib_update_nr_variant_default (vlib_node_registration_t * nr, u8 * variant)
|
||||
vlib_update_nr_variant_default (vlib_node_fn_registration_t * fnr,
|
||||
u8 * variant)
|
||||
{
|
||||
vlib_node_fn_registration_t *fnr = nr->node_fn_registrations;
|
||||
vlib_node_fn_registration_t *p_reg = 0;
|
||||
vlib_node_fn_registration_t *v_reg = 0;
|
||||
u32 tmp;
|
||||
@@ -127,6 +128,8 @@ vlib_early_node_config (vlib_main_t * vm, unformat_input_t * input)
|
||||
{
|
||||
clib_error_t *error = 0;
|
||||
vlib_node_registration_t *nr, **all;
|
||||
vnet_device_class_t *c;
|
||||
vnet_main_t *vnm = vnet_get_main ();
|
||||
unformat_input_t sub_input;
|
||||
uword *hash = 0, *p;
|
||||
u8 *variant = 0;
|
||||
@@ -161,10 +164,20 @@ vlib_early_node_config (vlib_main_t * vm, unformat_input_t * input)
|
||||
nr = vm->node_main.node_registrations;
|
||||
while (nr)
|
||||
{
|
||||
vlib_update_nr_variant_default (nr, variant);
|
||||
vlib_update_nr_variant_default (nr->node_fn_registrations,
|
||||
variant);
|
||||
nr = nr->next_registration;
|
||||
}
|
||||
|
||||
/* also apply it to interfaces */
|
||||
c = vnm->device_class_registrations;
|
||||
while (c)
|
||||
{
|
||||
vlib_update_nr_variant_default (c->tx_fn_registrations,
|
||||
variant);
|
||||
c = c->next_class_registration;
|
||||
}
|
||||
|
||||
vec_free (variant);
|
||||
}
|
||||
}
|
||||
@@ -192,7 +205,8 @@ vlib_early_node_config (vlib_main_t * vm, unformat_input_t * input)
|
||||
"please specify a valid node variant");
|
||||
vec_add1 (variant, 0);
|
||||
|
||||
vlib_update_nr_variant_default (nr, variant);
|
||||
vlib_update_nr_variant_default (nr->node_fn_registrations,
|
||||
variant);
|
||||
|
||||
vec_free (variant);
|
||||
}
|
||||
|
||||
@@ -258,8 +258,8 @@ adj_glean_get_src (fib_protocol_t proto,
|
||||
u32 sw_if_index,
|
||||
const ip46_address_t *nh)
|
||||
{
|
||||
const ip46_address_t *conn, *source;
|
||||
const ip_adjacency_t *adj;
|
||||
ip46_address_t *conn;
|
||||
adj_index_t ai;
|
||||
|
||||
if (vec_len(adj_gleans[proto]) <= sw_if_index ||
|
||||
@@ -274,23 +274,33 @@ adj_glean_get_src (fib_protocol_t proto,
|
||||
if (nh)
|
||||
pfx.fp_addr = *nh;
|
||||
|
||||
/*
|
||||
* An interface can have more than one glean address. Where
|
||||
* possible we want to return a source address from the same
|
||||
* subnet as the destination. If this is not possible then any address
|
||||
* will do.
|
||||
*/
|
||||
source = NULL;
|
||||
|
||||
hash_foreach_mem(conn, ai, adj_gleans[proto][sw_if_index],
|
||||
({
|
||||
adj = adj_get(ai);
|
||||
|
||||
if (adj->sub_type.glean.rx_pfx.fp_len > 0)
|
||||
{
|
||||
source = &adj->sub_type.glean.rx_pfx.fp_addr;
|
||||
|
||||
/* if no destination is specified use the just glean */
|
||||
if (NULL == nh)
|
||||
return (&adj->sub_type.glean.rx_pfx.fp_addr);
|
||||
return (source);
|
||||
|
||||
/* check the clean covers the desintation */
|
||||
if (fib_prefix_is_cover(&adj->sub_type.glean.rx_pfx, &pfx))
|
||||
return (&adj->sub_type.glean.rx_pfx.fp_addr);
|
||||
return (source);
|
||||
}
|
||||
}));
|
||||
|
||||
return (NULL);
|
||||
return (source);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -306,7 +306,7 @@ typedef struct
|
||||
i16 integ_start_offset;
|
||||
u32 crypto_total_length;
|
||||
/* adj total_length for integ, e.g.4 bytes for IPSec ESN */
|
||||
u16 integ_length_adj;
|
||||
i16 integ_length_adj;
|
||||
u8 *iv;
|
||||
union
|
||||
{
|
||||
@@ -605,7 +605,7 @@ vnet_crypto_async_add_to_frame (vlib_main_t * vm,
|
||||
u32 key_index,
|
||||
u32 crypto_len, i16 integ_len_adj,
|
||||
i16 crypto_start_offset,
|
||||
u16 integ_start_offset,
|
||||
i16 integ_start_offset,
|
||||
u32 buffer_index,
|
||||
u16 next_node,
|
||||
u8 * iv, u8 * tag, u8 * aad, u8 flags)
|
||||
|
||||
@@ -807,7 +807,7 @@ vnet_register_interface (vnet_main_t * vnm,
|
||||
vnet_config_main_t *cm;
|
||||
u32 hw_index, i;
|
||||
char *tx_node_name = NULL, *output_node_name = NULL;
|
||||
vlib_node_function_t *output_node = vnet_interface_output_node_get ();
|
||||
vlib_node_function_t *output_node = vnet_interface_output_node_get (vm);
|
||||
|
||||
pool_get (im->hw_interfaces, hw);
|
||||
clib_memset (hw, 0, sizeof (*hw));
|
||||
|
||||
@@ -326,6 +326,7 @@ CLIB_MARCH_SFX (devclass##_tx_fn_multiarch_register) (void) \
|
||||
vlib_node_fn_registration_t *r; \
|
||||
r = &CLIB_MARCH_SFX (devclass##_tx_fn_registration); \
|
||||
r->priority = CLIB_MARCH_FN_PRIORITY(); \
|
||||
r->name = CLIB_MARCH_VARIANT_STR; \
|
||||
r->next_registration = devclass.tx_fn_registrations; \
|
||||
devclass.tx_fn_registrations = r; \
|
||||
} \
|
||||
@@ -918,7 +919,7 @@ void vnet_pcap_drop_trace_filter_add_del (u32 error_index, int is_add);
|
||||
|
||||
int vnet_interface_name_renumber (u32 sw_if_index, u32 new_show_dev_instance);
|
||||
|
||||
vlib_node_function_t *vnet_interface_output_node_get (void);
|
||||
vlib_node_function_t *vnet_interface_output_node_get (vlib_main_t * vm);
|
||||
|
||||
void vnet_register_format_buffer_opaque_helper
|
||||
(vnet_buffer_opquae_formatter_t fn);
|
||||
|
||||
@@ -513,9 +513,35 @@ CLIB_MARCH_FN_REGISTRATION (vnet_interface_output_node);
|
||||
|
||||
#ifndef CLIB_MARCH_VARIANT
|
||||
vlib_node_function_t *
|
||||
vnet_interface_output_node_get (void)
|
||||
vnet_interface_output_node_get (vlib_main_t * vm)
|
||||
{
|
||||
return CLIB_MARCH_FN_POINTER (vnet_interface_output_node);
|
||||
vlib_node_function_t *fn = 0;
|
||||
vlib_node_fn_registration_t *fnr;
|
||||
char *name = 0;
|
||||
vlib_node_t *node = vlib_get_node_by_name (vm, (u8 *) "interface-output");
|
||||
ASSERT (node);
|
||||
|
||||
/* search for the same name */
|
||||
fnr = node->node_fn_registrations;
|
||||
while (fnr)
|
||||
{
|
||||
if (fnr->function == node->function)
|
||||
{
|
||||
name = fnr->name;
|
||||
break;
|
||||
}
|
||||
fnr = fnr->next_registration;
|
||||
}
|
||||
|
||||
if (name)
|
||||
{
|
||||
fn = CLIB_MARCH_FN_POINTER_BY_NAME (vnet_interface_output_node, name);
|
||||
}
|
||||
if (!fn) /* revert to march type selection if search failed */
|
||||
{
|
||||
fn = CLIB_MARCH_FN_POINTER (vnet_interface_output_node);
|
||||
}
|
||||
return fn;
|
||||
}
|
||||
#endif /* CLIB_MARCH_VARIANT */
|
||||
|
||||
|
||||
@@ -233,6 +233,24 @@ esp_get_ip6_hdr_len (ip6_header_t * ip6, ip6_ext_header_t ** ext_hdr)
|
||||
return len;
|
||||
}
|
||||
|
||||
/* IPsec IV generation: IVs requirements differ depending of the
|
||||
* encryption mode: IVs must be unpredictable for AES-CBC whereas it can
|
||||
* be predictable but should never be reused with the same key material
|
||||
* for CTR and GCM.
|
||||
* We use a packet counter as the IV for CTR and GCM, and to ensure the
|
||||
* IV is unpredictable for CBC, it is then encrypted using the same key
|
||||
* as the message. You can refer to NIST SP800-38a and NIST SP800-38d
|
||||
* for more details. */
|
||||
static_always_inline void *
|
||||
esp_generate_iv (ipsec_sa_t * sa, void *payload, int iv_sz)
|
||||
{
|
||||
ASSERT (iv_sz >= sizeof (u64));
|
||||
u64 *iv = (u64 *) (payload - iv_sz);
|
||||
clib_memset_u8 (iv, 0, iv_sz);
|
||||
*iv = sa->iv_counter++;
|
||||
return iv;
|
||||
}
|
||||
|
||||
static_always_inline void
|
||||
esp_process_chained_ops (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
vnet_crypto_op_t * ops, vlib_buffer_t * b[],
|
||||
@@ -395,10 +413,16 @@ esp_prepare_sync_op (vlib_main_t * vm, ipsec_per_thread_data_t * ptd,
|
||||
vnet_crypto_op_t *op;
|
||||
vec_add2_aligned (crypto_ops[0], op, 1, CLIB_CACHE_LINE_BYTES);
|
||||
vnet_crypto_op_init (op, sa0->crypto_enc_op_id);
|
||||
u8 *crypto_start = payload;
|
||||
/* esp_add_footer_and_icv() in esp_encrypt_inline() makes sure we always
|
||||
* have enough space for ESP header and footer which includes ICV */
|
||||
ASSERT (payload_len > icv_sz);
|
||||
u16 crypto_len = payload_len - icv_sz;
|
||||
|
||||
/* generate the IV in front of the payload */
|
||||
void *pkt_iv = esp_generate_iv (sa0, payload, iv_sz);
|
||||
|
||||
op->src = op->dst = payload;
|
||||
op->key_index = sa0->crypto_key_index;
|
||||
op->len = payload_len - icv_sz;
|
||||
op->user_data = b - bufs;
|
||||
|
||||
if (ipsec_sa_is_set_IS_AEAD (sa0))
|
||||
@@ -410,18 +434,21 @@ esp_prepare_sync_op (vlib_main_t * vm, ipsec_per_thread_data_t * ptd,
|
||||
op->aad = payload - hdr_len - sizeof (esp_aead_t);
|
||||
op->aad_len = esp_aad_fill (op->aad, esp, sa0);
|
||||
|
||||
op->tag = payload + op->len;
|
||||
op->tag = payload + crypto_len;
|
||||
op->tag_len = 16;
|
||||
|
||||
u64 *iv = (u64 *) (payload - iv_sz);
|
||||
nonce->salt = sa0->salt;
|
||||
nonce->iv = *iv = clib_host_to_net_u64 (sa0->gcm_iv_counter++);
|
||||
nonce->iv = *(u64 *) pkt_iv;
|
||||
op->iv = (u8 *) nonce;
|
||||
}
|
||||
else
|
||||
{
|
||||
op->iv = payload - iv_sz;
|
||||
op->flags = VNET_CRYPTO_OP_FLAG_INIT_IV;
|
||||
/* construct zero iv in front of the IP header */
|
||||
op->iv = pkt_iv - hdr_len - iv_sz;
|
||||
clib_memset_u8 (op->iv, 0, iv_sz);
|
||||
/* include iv field in crypto */
|
||||
crypto_start -= iv_sz;
|
||||
crypto_len += iv_sz;
|
||||
}
|
||||
|
||||
if (lb != b[0])
|
||||
@@ -430,8 +457,15 @@ esp_prepare_sync_op (vlib_main_t * vm, ipsec_per_thread_data_t * ptd,
|
||||
op->flags |= VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS;
|
||||
op->chunk_index = vec_len (ptd->chunks);
|
||||
op->tag = vlib_buffer_get_tail (lb) - icv_sz;
|
||||
esp_encrypt_chain_crypto (vm, ptd, sa0, b[0], lb, icv_sz, payload,
|
||||
payload_len, &op->n_chunks);
|
||||
esp_encrypt_chain_crypto (vm, ptd, sa0, b[0], lb, icv_sz,
|
||||
crypto_start, crypto_len + icv_sz,
|
||||
&op->n_chunks);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* not chained */
|
||||
op->src = op->dst = crypto_start;
|
||||
op->len = crypto_len;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,16 +515,19 @@ esp_prepare_async_frame (vlib_main_t * vm, ipsec_per_thread_data_t * ptd,
|
||||
u8 *tag, *iv, *aad = 0;
|
||||
u8 flag = 0;
|
||||
u32 key_index;
|
||||
i16 crypto_start_offset, integ_start_offset = 0;
|
||||
i16 crypto_start_offset, integ_start_offset;
|
||||
u16 crypto_total_len, integ_total_len;
|
||||
|
||||
post->next_index = next;
|
||||
|
||||
/* crypto */
|
||||
crypto_start_offset = payload - b->data;
|
||||
crypto_start_offset = integ_start_offset = payload - b->data;
|
||||
crypto_total_len = integ_total_len = payload_len - icv_sz;
|
||||
tag = payload + crypto_total_len;
|
||||
|
||||
/* generate the IV in front of the payload */
|
||||
void *pkt_iv = esp_generate_iv (sa, payload, iv_sz);
|
||||
|
||||
/* aead */
|
||||
if (ipsec_sa_is_set_IS_AEAD (sa))
|
||||
{
|
||||
@@ -501,7 +538,7 @@ esp_prepare_async_frame (vlib_main_t * vm, ipsec_per_thread_data_t * ptd,
|
||||
esp_aad_fill (aad, esp, sa);
|
||||
nonce = (esp_gcm_nonce_t *) (aad - sizeof (*nonce));
|
||||
nonce->salt = sa->salt;
|
||||
nonce->iv = *pkt_iv = clib_host_to_net_u64 (sa->gcm_iv_counter++);
|
||||
nonce->iv = *(u64 *) pkt_iv;
|
||||
iv = (u8 *) nonce;
|
||||
key_index = sa->crypto_key_index;
|
||||
|
||||
@@ -511,25 +548,38 @@ esp_prepare_async_frame (vlib_main_t * vm, ipsec_per_thread_data_t * ptd,
|
||||
flag |= VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS;
|
||||
tag = vlib_buffer_get_tail (lb) - icv_sz;
|
||||
crypto_total_len = esp_encrypt_chain_crypto (vm, ptd, sa, b, lb,
|
||||
icv_sz, payload,
|
||||
payload_len, 0);
|
||||
icv_sz,
|
||||
b->data +
|
||||
crypto_start_offset,
|
||||
crypto_total_len +
|
||||
icv_sz, 0);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* construct zero iv in front of the IP header */
|
||||
iv = pkt_iv - hdr_len - iv_sz;
|
||||
clib_memset_u8 (iv, 0, iv_sz);
|
||||
/* include iv field in crypto */
|
||||
crypto_start_offset -= iv_sz;
|
||||
crypto_total_len += iv_sz;
|
||||
}
|
||||
|
||||
/* cipher then hash */
|
||||
iv = payload - iv_sz;
|
||||
integ_start_offset = crypto_start_offset - iv_sz - sizeof (esp_header_t);
|
||||
integ_start_offset -= iv_sz + sizeof (esp_header_t);
|
||||
integ_total_len += iv_sz + sizeof (esp_header_t);
|
||||
flag |= VNET_CRYPTO_OP_FLAG_INIT_IV;
|
||||
key_index = sa->linked_key_index;
|
||||
|
||||
if (b != lb)
|
||||
{
|
||||
flag |= VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS;
|
||||
crypto_total_len = esp_encrypt_chain_crypto (vm, ptd, sa, b, lb,
|
||||
icv_sz, payload,
|
||||
payload_len, 0);
|
||||
icv_sz,
|
||||
b->data +
|
||||
crypto_start_offset,
|
||||
crypto_total_len + icv_sz,
|
||||
0);
|
||||
tag = vlib_buffer_get_tail (lb) - icv_sz;
|
||||
integ_total_len = esp_encrypt_chain_integ (vm, ptd, sa, b, lb, icv_sz,
|
||||
payload - iv_sz -
|
||||
|
||||
@@ -152,7 +152,7 @@ typedef struct
|
||||
|
||||
CLIB_CACHE_LINE_ALIGN_MARK (cacheline1);
|
||||
|
||||
u64 gcm_iv_counter;
|
||||
u64 iv_counter;
|
||||
union
|
||||
{
|
||||
ip4_header_t ip4_hdr;
|
||||
|
||||
+8
-10
@@ -98,10 +98,8 @@ static void
|
||||
vl_api_l2_xconnect_dump_t_handler (vl_api_l2_xconnect_dump_t * mp)
|
||||
{
|
||||
vl_api_registration_t *reg;
|
||||
vnet_main_t *vnm = vnet_get_main ();
|
||||
vnet_interface_main_t *im = &vnm->interface_main;
|
||||
l2input_main_t *l2im = &l2input_main;
|
||||
vnet_sw_interface_t *swif;
|
||||
u32 sw_if_index;
|
||||
l2_input_config_t *config;
|
||||
|
||||
reg = vl_api_client_index_to_registration (mp->client_index);
|
||||
@@ -109,13 +107,13 @@ vl_api_l2_xconnect_dump_t_handler (vl_api_l2_xconnect_dump_t * mp)
|
||||
return;
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
pool_foreach (swif, im->sw_interfaces)
|
||||
{
|
||||
config = vec_elt_at_index (l2im->configs, swif->sw_if_index);
|
||||
if (l2_input_is_xconnect(config))
|
||||
send_l2_xconnect_details (reg, mp->context, swif->sw_if_index,
|
||||
config->output_sw_if_index);
|
||||
}
|
||||
vec_foreach_index (sw_if_index, l2im->configs)
|
||||
{
|
||||
config = vec_elt_at_index (l2im->configs, sw_if_index);
|
||||
if (l2_input_is_xconnect (config))
|
||||
send_l2_xconnect_details (reg, mp->context, sw_if_index,
|
||||
config->output_sw_if_index);
|
||||
}
|
||||
/* *INDENT-ON* */
|
||||
}
|
||||
|
||||
|
||||
@@ -84,9 +84,29 @@ clib_march_select_fn_ptr (clib_march_fn_registration * r)
|
||||
return rv;
|
||||
}
|
||||
|
||||
static_always_inline void *
|
||||
clib_march_select_fn_ptr_by_name (clib_march_fn_registration * r, char *name)
|
||||
{
|
||||
void *rv = 0;
|
||||
|
||||
while (r)
|
||||
{
|
||||
if (strncmp (name, r->name, vec_len (r->name) - 1) == 0)
|
||||
{
|
||||
rv = r->function;
|
||||
break;
|
||||
}
|
||||
r = r->next;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
#define CLIB_MARCH_FN_POINTER(fn) \
|
||||
clib_march_select_fn_ptr (fn##_march_fn_registrations);
|
||||
|
||||
#define CLIB_MARCH_FN_POINTER_BY_NAME(fn, name) \
|
||||
clib_march_select_fn_ptr_by_name (fn##_march_fn_registrations, name);
|
||||
|
||||
#define _CLIB_MARCH_FN_REGISTRATION(fn) \
|
||||
static clib_march_fn_registration \
|
||||
CLIB_MARCH_SFX(fn##_march_fn_registration) = \
|
||||
|
||||
+25
-1
@@ -7,7 +7,7 @@ from scapy.packet import Raw
|
||||
|
||||
from framework import VppTestCase
|
||||
from util import ppp
|
||||
from vpp_ip_route import VppIpInterfaceAddress
|
||||
from vpp_ip_route import VppIpInterfaceAddress, VppIpRoute, VppRoutePath
|
||||
from vpp_neighbor import VppNeighbor
|
||||
|
||||
""" TestPing is a subclass of VPPTestCase classes.
|
||||
@@ -150,3 +150,27 @@ class TestPing(VppTestCase):
|
||||
for p in out:
|
||||
icmp = self.verify_ping_request(p, "10.0.0.1", nbr_addr, icmp_seq)
|
||||
icmp_seq = icmp_seq + 1
|
||||
|
||||
def test_ping_fib_routed_dst(self):
|
||||
""" ping destination routed according to FIB table """
|
||||
|
||||
try:
|
||||
self.pg1.generate_remote_hosts(1)
|
||||
self.pg_enable_capture(self.pg_interfaces)
|
||||
self.pg_start()
|
||||
routed_dst = "10.0.2.0"
|
||||
self.logger.info(self.vapi.cli("show ip4 neighbors"))
|
||||
VppIpRoute(self, routed_dst, 24,
|
||||
[VppRoutePath(self.pg1.remote_hosts[0].ip4,
|
||||
self.pg1.sw_if_index)]).add_vpp_config()
|
||||
ping_cmd = "ping %s interval 0.01 repeat 3" % routed_dst
|
||||
ret = self.vapi.cli(ping_cmd)
|
||||
self.logger.info(ret)
|
||||
out = self.pg1.get_capture(3)
|
||||
icmp_seq = 1
|
||||
for p in out:
|
||||
self.verify_ping_request(p, self.pg1.local_ip4, routed_dst,
|
||||
icmp_seq)
|
||||
icmp_seq = icmp_seq + 1
|
||||
finally:
|
||||
self.vapi.cli("show error")
|
||||
|
||||
Reference in New Issue
Block a user